Beispiel #1
0
    // The same mode also handles creation of new homes.
    private static void HandleMoveToHome(GameSession session, PacketReader packet)
    {
        int    homeTemplate = packet.ReadInt();
        Player player       = session.Player;

        if (player.Account.Home == null)
        {
            player.Account.Home = new(player.Account.Id, player.Name, homeTemplate);
            GameServer.HomeManager.AddHome(player.Account.Home);

            // Send inventories
            session.Send(WarehouseInventoryPacket.StartList());
            int counter = 0;
            foreach (KeyValuePair <long, Item> kvp in player.Account.Home.WarehouseInventory)
            {
                session.Send(WarehouseInventoryPacket.Load(kvp.Value, ++counter));
            }
            session.Send(WarehouseInventoryPacket.EndList());

            session.Send(FurnishingInventoryPacket.StartList());
            foreach (Cube cube in player.Account.Home.FurnishingInventory.Values.Where(x => x.Item != null))
            {
                session.Send(FurnishingInventoryPacket.Load(cube));
            }
            session.Send(FurnishingInventoryPacket.EndList());
        }
        Home home = GameServer.HomeManager.GetHomeById(player.Account.Home.Id);

        player.VisitingHomeId = player.Account.Home.Id;
        player.Guide          = null;

        player.WarpGameToGame(home.MapId, home.InstanceId);
    }
        public Item AddWarehouseItem(GameSession session, int itemId, int amount, Item item = default)
        {
            Item furnishingItem = WarehouseInventory.Values.FirstOrDefault(x => x.Id == itemId);

            if (furnishingItem == default)
            {
                furnishingItem = item == default ? new Item(itemId, amount) : item;
                WarehouseInventory[furnishingItem.Uid] = furnishingItem;
                session.Send(WarehouseInventoryPacket.Load(furnishingItem, WarehouseInventory.Values.Count));
                session.Send(WarehouseInventoryPacket.Count(WarehouseInventory.Values.Count + 1));
            }
            else
            {
                WarehouseInventory[furnishingItem.Uid].Amount += amount;
                session.Send(WarehouseInventoryPacket.UpdateAmount(furnishingItem.Uid, furnishingItem.Amount));
            }
            return(furnishingItem);
        }
Beispiel #3
0
        public override void Handle(GameSession session, PacketReader packet)
        {
            long     accountId = packet.ReadLong();
            AuthData authData  = AuthStorage.GetData(accountId);

            // Backwards seeking because we read accountId here
            packet.Skip(-8);
            HandleCommon(session, packet);

            Player player = DatabaseManager.GetCharacter(authData.CharacterId);

            if (player == default)
            {
                throw new ArgumentException("Character not found!");
            }

            player.Session = session;

            session.InitPlayer(player);

            //session.Send(0x27, 0x01); // Meret market related...?
            session.Send(BuddyPacket.Initialize());

            session.Send(LoginPacket.LoginRequired(accountId));

            if (session.Player.Guild != null)
            {
                Guild guild = DatabaseManager.GetGuild(session.Player.Guild.Id);
                session.Send(GuildPacket.UpdateGuild(guild));
                session.Send(GuildPacket.MemberJoin(player));
            }
            session.Send(BuddyPacket.LoadList(player));
            session.Send(BuddyPacket.EndList(player.BuddyList.Count));

            // Meret market
            //session.Send("6E 00 0B 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray());
            //session.Send("6E 00 0C 00 00 00 00".ToByteArray());
            // UserConditionEvent
            //session.Send("BF 00 00 00 00 00 00".ToByteArray());
            // PCBangBonus
            //session.Send("A7 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray());
            TimeSyncPacket.SetInitial1();
            TimeSyncPacket.SetInitial2();
            TimeSyncPacket.Request();
            session.Send(StatPacket.SetStats(session.FieldPlayer));
            // TODO: Grab Hp/Spirit/Stam from last login
            player.Stats.InitializePools(player.Stats[PlayerStatId.Hp].Max, player.Stats[PlayerStatId.Spirit].Max, player.Stats[PlayerStatId.Stamina].Max);

            session.SyncTicks();
            session.Send(DynamicChannelPacket.DynamicChannel());
            session.Send(ServerEnterPacket.Enter(session));
            // SendUgc f(0x16), SendCash f(0x09), SendContentShutdown f(0x01, 0x04), SendPvp f(0x0C)
            PacketWriter pWriter = PacketWriter.Of(SendOp.SYNC_NUMBER);

            pWriter.WriteByte();
            session.Send(pWriter);
            // 0x112, Prestige f(0x00, 0x07)
            session.Send(PrestigePacket.Prestige(session.Player));

            // Load inventory tabs
            foreach (InventoryTab tab in Enum.GetValues(typeof(InventoryTab)))
            {
                InventoryController.LoadInventoryTab(session, tab);
            }

            List <QuestMetadata> questList = QuestMetadataStorage.GetAvailableQuests(player.Levels.Level); // TODO: This logic needs to be refactored when DB is implemented

            questList.Add(QuestMetadataStorage.GetMetadata(60100000));                                     // Manually adding "the caravan" for testing purposes

            foreach (QuestMetadata quest in questList)
            {
                session.Player.QuestList.Add(new QuestStatus(quest));
            }

            IEnumerable <List <QuestStatus> > packetCount = SplitList(session.Player.QuestList, 200); // Split the quest list in 200 quests per packet, same way kms do

            foreach (List <QuestStatus> item in packetCount)
            {
                session.Send(QuestPacket.SendQuests(item));
            }

            session.Send(TrophyPacket.WriteTableStart());
            List <Trophy> trophyList = new List <Trophy>(session.Player.TrophyData.Values);
            IEnumerable <List <Trophy> > trophyListPackets = SplitList(trophyList, 60);

            foreach (List <Trophy> trophy in trophyListPackets)
            {
                session.Send(TrophyPacket.WriteTableContent(trophy));
            }

            session.Send(WarehouseInventoryPacket.Count()); // Typically sent after buddylist
            session.Send(WarehouseInventoryPacket.StartList());
            session.Send(WarehouseInventoryPacket.EndList());
            session.Send(FurnishingInventoryPacket.StartList());
            session.Send(FurnishingInventoryPacket.EndList());
            // SendQuest, SendAchieve, SendManufacturer, SendUserMaid
            session.Send(UserEnvPacket.SetTitles(player));
            session.Send(UserEnvPacket.Send04());
            session.Send(UserEnvPacket.Send05());
            session.Send(UserEnvPacket.Send08());
            session.Send(UserEnvPacket.Send09());
            session.Send(UserEnvPacket.Send10());
            session.Send(UserEnvPacket.Send12());

            // SendMeretMarket f(0xC9)
            session.Send(FishingPacket.LoadAlbum(player));
            // SendPvp f(0x16,0x17), ResponsePet f(0x07), 0xF6
            // CharacterAbility
            // E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

            // Normally, options are only requested for a new character. Since we don't have a database, we'll always requests the users bindings
            session.Send(KeyTablePacket.RequestDefault());
            // TODO - Ask for mouse or kb controls on new character creation.
            // Commented out since its annoying to click every time
            //session.Send(KeyTablePacket.AskKeyboardOrMouse());

            // Key bindings and skill slots would normally be loaded from a database
            // If the character is not a new character, this is what we would send
            // session.Send(KeyTablePacket.SendFullOptions(session.Player.Options));

            // SendKeyTable f(0x00), SendGuideRecord f(0x03), GameEvent f(0x00)
            // SendBannerList f(0x19), SendRoomDungeon f(0x05, 0x14, 0x17)
            // FieldEntrance
            session.Send("19 00 00 65 00 00 00 29 7C 7D 01 0C 4D A1 6F 01 0C D3 1A 5F 01 0C EF 03 00 00 01 A2 3C 31 01 0C 3F 0C B7 0D 01 6B 55 5F 01 0C 3A 77 31 01 0C B1 98 BA 01 0C 03 90 5F 01 0C F9 7A 40 01 0C 91 B5 40 01 0C F9 57 31 01 0C 2F C7 BB 0D 01 81 97 7D 01 0C C2 70 5F 01 0C 51 96 40 01 0C B9 38 31 01 0C 41 78 7D 01 0C 65 9D 6F 01 0C 83 51 5F 01 0C 52 73 31 01 0C FF E0 B8 0D 01 11 77 40 01 0C A9 B1 40 01 0C 11 54 31 01 0C DA 6C 5F 01 0C 69 92 40 01 0C D1 34 31 01 0C 7D 99 6F 01 0C 03 13 5F 01 0C 69 6F 31 01 0C 32 88 5F 01 0C 9B 4D 5F 01 0C FF 6F B6 0D 01 29 73 40 01 0C C1 AD 40 01 0C 29 50 31 01 0C 81 8E 40 01 0C E9 30 31 01 0C 09 CE 8C 01 0C 95 95 6F 01 0C 1B 0F 5F 01 0C 4A 84 5F 01 0C B3 49 5F 01 0C 82 6B 31 01 0C 4F 15 BC 0D 01 F9 8C BA 01 00 D9 A9 40 01 0C 41 4C 31 01 0C EF B9 B8 0D 01 99 8A 40 01 0C 21 CA 8C 01 0C 01 AD 6F 01 0C 33 0B 5F 01 0C 99 67 31 01 0C 62 80 5F 01 0C CB 45 5F 01 0C 79 08 9C 01 0C F1 A5 40 01 0C E1 87 7D 01 0C BB 9B 5F 01 0C B1 86 40 01 0C 39 C6 8C 01 0C 7A 7C 5F 01 0C B2 63 31 01 0C 29 85 BA 01 0E 91 04 9C 01 0C 09 A2 40 01 0C 71 44 31 01 0C F9 83 7D 01 0C 1D A9 6F 01 0C D3 97 5F 01 0C C9 82 40 01 0C 51 C2 8C 01 0C 61 BD 40 01 0C C9 5F 31 01 0C 51 9F 7D 01 0C 92 78 5F 01 0C 0F 08 B9 0D 01 A9 00 9C 01 0C 89 40 31 01 0C 11 80 7D 01 0C 35 A5 6F 01 0C BB 1E 5F 01 0C 53 59 5F 01 0C E9 03 00 00 01 22 7B 31 01 0C EB 93 5F 01 0C EA 03 00 00 01 E1 7E 40 01 0C 69 BE 8C 01 0C 79 B9 40 01 0C E1 5B 31 01 0C EB 03 00 00 01 69 9B 7D 01 0C AA 74 5F 01 0C EC 03 00 00 01 ED 03 00 00 01 C1 FC 9B 01 0C EE 03 00 00 01".ToByteArray());
            // 0xF0, ResponsePet P(0F 01)
            // RequestFieldEnter
            //session.Send("16 00 00 41 75 19 03 00 01 8A 42 0F 00 00 00 00 00 00 C0 28 C4 00 40 03 44 00 00 16 44 00 00 00 00 00 00 00 00 55 FF 33 42 E8 49 01 00".ToByteArray());
            session.Send(FieldPacket.RequestEnter(session.FieldPlayer));
            // SendUgc: 15 01 00 00 00 00 00 00 00 00 00 00 00 4B 00 00 00
            // SendHomeCommand: 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00

            //session.Send("B9 00 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00".ToByteArray());
            //session.Send(ServerEnterPacket.Confirm());

            //session.Send(0xF0, 0x00, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00);
            //session.Send(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
            //session.Send(ServerEnterPacket.Confirm());
        }
    public override void Handle(GameSession session, PacketReader packet)
    {
        long     accountId = packet.ReadLong();
        AuthData authData  = DatabaseManager.AuthData.GetByAccountId(accountId);

        Player dbPlayer = DatabaseManager.Characters.FindPlayerById(authData.OnlineCharacterId, session);

        // Backwards seeking because we read accountId here
        packet.Skip(-8);
        HandleCommon(session, packet);

        session.InitPlayer(dbPlayer);

        Player player = session.Player;

        player.BuddyList = GameServer.BuddyManager.GetBuddies(player.CharacterId);
        player.Mailbox   = GameServer.MailManager.GetMails(player.CharacterId);

        GameServer.PlayerManager.AddPlayer(player);
        GameServer.BuddyManager.SetFriendSessions(player);

        // Only send buddy login notification if player is not changing channels
        if (!player.IsMigrating)
        {
            player.UpdateBuddies();
        }

        if (player.GuildId != 0)
        {
            Guild guild = GameServer.GuildManager.GetGuildById(player.GuildId);
            player.Guild = guild;
            GuildMember guildMember = guild.Members.First(x => x.Id == player.CharacterId);
            guildMember.Player.Session = session;
            player.GuildMember         = guildMember;
            session.Send(GuildPacket.UpdateGuild(guild));
            guild.BroadcastPacketGuild(GuildPacket.MemberJoin(player));
            guild.BroadcastPacketGuild(GuildPacket.MemberLoggedIn(player), session);
        }

        player.IsMigrating = false;

        //session.Send(0x27, 0x01); // Meret market related...?
        session.Send(MushkingRoyaleSystemPacket.LoadStats(player.Account.MushkingRoyaleStats));
        session.Send(MushkingRoyaleSystemPacket.LoadMedals(player.Account));

        player.GetUnreadMailCount();
        session.Send(BuddyPacket.Initialize());
        session.Send(BuddyPacket.LoadList(player.BuddyList));
        session.Send(BuddyPacket.EndList(player.BuddyList.Count));

        // Meret market
        //session.Send("6E 00 0B 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray());
        //session.Send("6E 00 0C 00 00 00 00".ToByteArray());
        // UserConditionEvent
        //session.Send("BF 00 00 00 00 00 00".ToByteArray());
        // PCBangBonus
        //session.Send("A7 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray());

        session.Send(TimeSyncPacket.SetInitial1());
        session.Send(TimeSyncPacket.SetInitial2());

        session.Send(StatPacket.SetStats(session.Player.FieldPlayer));
        // session.Send(StatPacket.SetStats(session.Player.FieldPlayer)); // Second packet is meant to send the stats initialized, for now we'll just send the first one

        session.Player.ClientTickSyncLoop();
        session.Send(DynamicChannelPacket.DynamicChannel(short.Parse(ConstantsMetadataStorage.GetConstant("ChannelCount"))));

        session.Send(ServerEnterPacket.Enter(session));
        session.Send(UgcPacket.Unknown22());
        session.Send(CashPacket.Unknown09());

        // SendContentShutdown f(0x01, 0x04)
        session.Send(PvpPacket.Mode0C());
        session.Send(SyncNumberPacket.Send());
        session.Send(SyncValuePacket.SetSyncValue(120000)); // unknown what this value means

        session.Send(PrestigePacket.SetLevels(player));
        session.Send(PrestigePacket.WeeklyMissions());

        // Load inventory tabs
        foreach (InventoryTab tab in Enum.GetValues(typeof(InventoryTab)))
        {
            player.Inventory.LoadInventoryTab(session, tab);
        }

        if (player.Account.HomeId != 0)
        {
            Home home = GameServer.HomeManager.GetHomeById(player.Account.HomeId);
            player.Account.Home = home;
            session.Send(WarehouseInventoryPacket.StartList());
            int counter = 0;
            foreach (KeyValuePair <long, Item> kvp in home.WarehouseInventory)
            {
                session.Send(WarehouseInventoryPacket.Load(kvp.Value, ++counter));
            }

            session.Send(WarehouseInventoryPacket.EndList());

            session.Send(FurnishingInventoryPacket.StartList());
            foreach (Cube cube in home.FurnishingInventory.Values.Where(x => x.Item != null))
            {
                session.Send(FurnishingInventoryPacket.Load(cube));
            }

            session.Send(FurnishingInventoryPacket.EndList());
        }

        session.Send(QuestPacket.StartList());
        session.Send(QuestPacket.Packet1F());
        session.Send(QuestPacket.Packet20());

        IEnumerable <List <QuestStatus> > packetCount = player.QuestData.Values.ToList().SplitList(200); // Split the quest list in 200 quests per packet

        foreach (List <QuestStatus> item in packetCount)
        {
            session.Send(QuestPacket.SendQuests(item));
        }

        session.Send(QuestPacket.EndList());

        session.Send(TrophyPacket.WriteTableStart());
        List <Trophy> trophyList = new(player.TrophyData.Values);
        IEnumerable <List <Trophy> > trophyListPackets = trophyList.SplitList(60);

        foreach (List <Trophy> trophy in trophyListPackets)
        {
            session.Send(TrophyPacket.WriteTableContent(trophy));
        }

        // SendQuest, SendAchieve, SendManufacturer, SendUserMaid
        session.Send(UserEnvPacket.SetTitles(player));
        session.Send(UserEnvPacket.Send04());
        session.Send(UserEnvPacket.Send05());
        session.Send(UserEnvPacket.UpdateLifeSkills(player.GatheringCount));
        session.Send(UserEnvPacket.Send09());
        session.Send(UserEnvPacket.Send10());
        session.Send(UserEnvPacket.Send12());

        session.Send(MeretMarketPacket.ModeC9());

        session.Send(FishingPacket.LoadAlbum(player));

        session.Send(PvpPacket.Mode16());
        session.Send(PvpPacket.Mode17());

        session.Send(ResponsePetPacket.Mode07());
        // LegionBattle (0xF6)
        // CharacterAbility
        // E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

        // Key bindings and skill slots would normally be loaded from a database
        // If the character is not a new character, this is what we would send
        session.Send(KeyTablePacket.SendFullOptions(player.GameOptions));

        if (player.MapId == (int)Map.UnknownLocation)  // tutorial map
        {
            session.Send(KeyTablePacket.AskKeyboardOrMouse());
        }

        // SendKeyTable f(0x00), SendGuideRecord f(0x03), GameEvent f(0x00)
        // SendBannerList f(0x19), SendRoomDungeon f(0x05, 0x14, 0x17)
        session.Send(DungeonListPacket.DungeonList());
        // 0xF0, ResponsePet P(0F 01)
        // RequestFieldEnter
        //session.Send("16 00 00 41 75 19 03 00 01 8A 42 0F 00 00 00 00 00 00 C0 28 C4 00 40 03 44 00 00 16 44 00 00 00 00 00 00 00 00 55 FF 33 42 E8 49 01 00".ToByteArray());
        session.Send(RequestFieldEnterPacket.RequestEnter(player.FieldPlayer));

        Party party = GameServer.PartyManager.GetPartyByMember(player.CharacterId);

        if (party != null)
        {
            player.Party = party;
            party.BroadcastPacketParty(PartyPacket.LoginNotice(player), session);
            session.Send(PartyPacket.Create(party, false));
        }

        // SendUgc: 15 01 00 00 00 00 00 00 00 00 00 00 00 4B 00 00 00
        // SendHomeCommand: 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00

        player.TimeSyncLoop();
        session.Send(TimeSyncPacket.SetSessionServerTick(0));
        //session.Send("B9 00 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00".ToByteArray());
        session.Send(ServerEnterPacket.Confirm());

        //session.Send(0xF0, 0x00, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00);
        //session.Send(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
    }
Beispiel #5
0
        // Adds item
        public static void Add(GameSession session, Item item, bool isNew)
        {
            // item is currency
            if (item.Id.ToString().StartsWith("9"))
            {
                switch (item.Id)
                {
                case 90000001:     // Meso
                    session.Player.Wallet.Meso.Modify(item.Amount);
                    break;

                case 90000006:     // Valor Token
                    session.Player.Wallet.ValorToken.Modify(item.Amount);
                    break;

                case 90000004:     // Meret
                case 90000011:     // Meret
                case 90000015:     // Meret
                case 90000016:     // Meret
                    session.Player.Account.Meret.Modify(item.Amount);
                    break;

                case 90000013:     // Rue
                    session.Player.Wallet.Rue.Modify(item.Amount);
                    break;

                case 90000014:     // Havi
                    session.Player.Wallet.HaviFruit.Modify(item.Amount);
                    break;

                case 90000017:     // Treva
                    session.Player.Wallet.Treva.Modify(item.Amount);
                    break;

                case 90000021:     // Guild Funds
                    if (session.Player.Guild != null)
                    {
                        session.Player.Guild.Funds += item.Amount;
                        session.Player.Guild.BroadcastPacketGuild(GuildPacket.UpdateGuildFunds(session.Player.Guild.Funds));
                        DatabaseManager.Guilds.Update(session.Player.Guild);
                    }
                    break;
                }
                return;
            }
            // TODO: Find a way to categorize items appropriately
            else if (item.Id.ToString().StartsWith("501") ||
                     item.Id.ToString().StartsWith("502") ||
                     item.Id.ToString().StartsWith("503") ||
                     item.Id.ToString().StartsWith("504") ||
                     item.Id.ToString().StartsWith("505"))
            {
                if (session.Player.Account.Home == null)
                {
                    return;
                }

                Home home = GameServer.HomeManager.GetHomeById(session.Player.Account.Home.Id);
                if (home == null)
                {
                    return;
                }

                _ = home.AddWarehouseItem(session, item.Id, item.Amount, item);
                session.Send(WarehouseInventoryPacket.GainItemMessage(item, item.Amount));
                return;
            }

            // Checks if item is stackable or not
            if (item.StackLimit > 1)
            {
                foreach (Item i in session.Player.Inventory.Items.Values)
                {
                    // Checks to see if item exists in database (dictionary)
                    if (i.Id != item.Id || i.Amount >= i.StackLimit || i.Rarity != item.Rarity)
                    {
                        continue;
                    }
                    // Updates inventory for item amount overflow
                    if ((i.Amount + item.Amount) > i.StackLimit)
                    {
                        int added = i.StackLimit - i.Amount;
                        item.Amount -= added;
                        i.Amount     = i.StackLimit;
                        session.Send(ItemInventoryPacket.Update(i.Uid, i.Amount));
                        session.Send(ItemInventoryPacket.MarkItemNew(i, added));
                    }
                    // Updates item amount
                    else
                    {
                        i.Amount += item.Amount;
                        session.Send(ItemInventoryPacket.Update(i.Uid, i.Amount));
                        session.Send(ItemInventoryPacket.MarkItemNew(i, item.Amount));
                        return;
                    }
                }

                if (!session.Player.Inventory.Add(item)) // Adds item into internal database
                {
                    return;
                }
                session.Send(ItemInventoryPacket.Add(item)); // Sends packet to add item clientside
                if (isNew)
                {
                    session.Send(ItemInventoryPacket.MarkItemNew(item, item.Amount)); // Marks Item as New
                }
                return;
            }

            if (item.Amount == 1)
            {
                if (!session.Player.Inventory.Add(item))
                {
                    return;
                }

                session.Send(ItemInventoryPacket.Add(item));
                if (isNew)
                {
                    session.Send(ItemInventoryPacket.MarkItemNew(item, item.Amount));
                }
                return;
            }

            for (int i = 0; i < item.Amount; i++)
            {
                Item newItem = new Item(item)
                {
                    Amount = 1,
                    Uid    = 0
                };
                newItem.Uid = DatabaseManager.Items.Insert(newItem);

                if (!session.Player.Inventory.Add(newItem))
                {
                    continue;
                }

                session.Send(ItemInventoryPacket.Add(newItem));
                if (isNew)
                {
                    session.Send(ItemInventoryPacket.MarkItemNew(newItem, newItem.Amount));
                }
            }
        }
    public override void Handle(GameSession session, PacketReader packet)
    {
        long     accountId = packet.ReadLong();
        AuthData authData  = DatabaseManager.AuthData.GetByAccountId(accountId);

        Player dbPlayer = DatabaseManager.Characters.FindPlayerById(authData.OnlineCharacterId);

        // Backwards seeking because we read accountId here
        packet.Skip(-8);
        HandleCommon(session, packet);

        session.InitPlayer(dbPlayer);

        Player player = session.Player;

        player.Session                             = session;
        player.Wallet.Meso.Session                 = session;
        player.Wallet.ValorToken.Session           = session;
        player.Wallet.Treva.Session                = session;
        player.Wallet.Rue.Session                  = session;
        player.Wallet.HaviFruit.Session            = session;
        player.Account.Meret.Session               = session;
        player.Account.GameMeret.Session           = session;
        player.Account.EventMeret.Session          = session;
        player.Account.MesoToken.Session           = session;
        player.Account.BankInventory.Mesos.Session = session;
        player.Levels.Player                       = player;
        player.BuddyList                           = GameServer.BuddyManager.GetBuddies(player.CharacterId);
        player.Mailbox                             = GameServer.MailManager.GetMails(player.CharacterId);

        GameServer.PlayerManager.AddPlayer(player);
        GameServer.BuddyManager.SetFriendSessions(player);

        // Only send buddy login notification if player is not changing channels
        if (!player.IsMigrating)
        {
            player.UpdateBuddies();
        }

        if (player.GuildId != 0)
        {
            Guild guild = GameServer.GuildManager.GetGuildById(player.GuildId);
            player.Guild = guild;
            GuildMember guildMember = guild.Members.First(x => x.Id == player.CharacterId);
            guildMember.Player.Session = session;
            player.GuildMember         = guildMember;
            session.Send(GuildPacket.UpdateGuild(guild));
            guild.BroadcastPacketGuild(GuildPacket.MemberJoin(player));
            guild.BroadcastPacketGuild(GuildPacket.MemberLoggedIn(player), session);
        }

        player.IsMigrating = false;

        //session.Send(0x27, 0x01); // Meret market related...?
        session.Send(MushkingRoyaleSystemPacket.LoadStats(session.Player.Account.MushkingRoyaleStats));
        session.Send(MushkingRoyaleSystemPacket.LoadMedals(session.Player.Account));

        player.GetUnreadMailCount();
        session.Send(BuddyPacket.Initialize());
        session.Send(BuddyPacket.LoadList(player.BuddyList));
        session.Send(BuddyPacket.EndList(player.BuddyList.Count));

        // Meret market
        //session.Send("6E 00 0B 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray());
        //session.Send("6E 00 0C 00 00 00 00".ToByteArray());
        // UserConditionEvent
        //session.Send("BF 00 00 00 00 00 00".ToByteArray());
        // PCBangBonus
        //session.Send("A7 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray());
        TimeSyncPacket.SetInitial1();
        TimeSyncPacket.SetInitial2();
        TimeSyncPacket.Request();
        session.Send(StatPacket.SetStats(session.Player.FieldPlayer));
        session.Player.ClientTickSyncLoop();
        session.Send(DynamicChannelPacket.DynamicChannel());
        session.Send(ServerEnterPacket.Enter(session));
        // SendUgc f(0x16), SendCash f(0x09), SendContentShutdown f(0x01, 0x04), SendPvp f(0x0C)
        session.Send(SyncNumberPacket.Send());
        // 0x112, Prestige f(0x00, 0x07)
        session.Send(PrestigePacket.Prestige(player));

        // Load inventory tabs
        foreach (InventoryTab tab in Enum.GetValues(typeof(InventoryTab)))
        {
            player.Inventory.LoadInventoryTab(session, tab);
        }

        if (player.Account.HomeId != 0)
        {
            Home home = GameServer.HomeManager.GetHomeById(player.Account.HomeId);
            player.Account.Home = home;
            session.Send(WarehouseInventoryPacket.StartList());
            int counter = 0;
            foreach (KeyValuePair <long, Item> kvp in home.WarehouseInventory)
            {
                session.Send(WarehouseInventoryPacket.Load(kvp.Value, ++counter));
            }
            session.Send(WarehouseInventoryPacket.EndList());

            session.Send(FurnishingInventoryPacket.StartList());
            foreach (Cube cube in home.FurnishingInventory.Values.Where(x => x.Item != null))
            {
                session.Send(FurnishingInventoryPacket.Load(cube));
            }
            session.Send(FurnishingInventoryPacket.EndList());
        }

        session.Send(QuestPacket.StartList());
        session.Send(QuestPacket.Packet1F());
        session.Send(QuestPacket.Packet20());

        IEnumerable <List <QuestStatus> > packetCount = player.QuestData.Values.ToList().SplitList(200); // Split the quest list in 200 quests per packet

        foreach (List <QuestStatus> item in packetCount)
        {
            session.Send(QuestPacket.SendQuests(item));
        }
        session.Send(QuestPacket.EndList());

        session.Send(TrophyPacket.WriteTableStart());
        List <Trophy> trophyList = new(player.TrophyData.Values);
        IEnumerable <List <Trophy> > trophyListPackets = trophyList.SplitList(60);

        foreach (List <Trophy> trophy in trophyListPackets)
        {
            session.Send(TrophyPacket.WriteTableContent(trophy));
        }

        // SendQuest, SendAchieve, SendManufacturer, SendUserMaid
        session.Send(UserEnvPacket.SetTitles(player));
        session.Send(UserEnvPacket.Send04());
        session.Send(UserEnvPacket.Send05());
        session.Send(UserEnvPacket.UpdateLifeSkills(player.GatheringCount));
        session.Send(UserEnvPacket.Send09());
        session.Send(UserEnvPacket.Send10());
        session.Send(UserEnvPacket.Send12());

        // SendMeretMarket f(0xC9)
        session.Send(FishingPacket.LoadAlbum(player));
        // SendPvp f(0x16,0x17), ResponsePet f(0x07), 0xF6
        // CharacterAbility
        // E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

        // Key bindings and skill slots would normally be loaded from a database
        // If the character is not a new character, this is what we would send
        session.Send(KeyTablePacket.SendFullOptions(player.GameOptions));

        if (player.MapId == (int)Map.UnknownLocation)  // tutorial map
        {
            session.Send(KeyTablePacket.AskKeyboardOrMouse());
        }

        // SendKeyTable f(0x00), SendGuideRecord f(0x03), GameEvent f(0x00)
        // SendBannerList f(0x19), SendRoomDungeon f(0x05, 0x14, 0x17)
        // FieldEntrance
        session.Send("19 00 00 65 00 00 00 29 7C 7D 01 0C 4D A1 6F 01 0C D3 1A 5F 01 0C EF 03 00 00 01 A2 3C 31 01 0C 3F 0C B7 0D 01 6B 55 5F 01 0C 3A 77 31 01 0C B1 98 BA 01 0C 03 90 5F 01 0C F9 7A 40 01 0C 91 B5 40 01 0C F9 57 31 01 0C 2F C7 BB 0D 01 81 97 7D 01 0C C2 70 5F 01 0C 51 96 40 01 0C B9 38 31 01 0C 41 78 7D 01 0C 65 9D 6F 01 0C 83 51 5F 01 0C 52 73 31 01 0C FF E0 B8 0D 01 11 77 40 01 0C A9 B1 40 01 0C 11 54 31 01 0C DA 6C 5F 01 0C 69 92 40 01 0C D1 34 31 01 0C 7D 99 6F 01 0C 03 13 5F 01 0C 69 6F 31 01 0C 32 88 5F 01 0C 9B 4D 5F 01 0C FF 6F B6 0D 01 29 73 40 01 0C C1 AD 40 01 0C 29 50 31 01 0C 81 8E 40 01 0C E9 30 31 01 0C 09 CE 8C 01 0C 95 95 6F 01 0C 1B 0F 5F 01 0C 4A 84 5F 01 0C B3 49 5F 01 0C 82 6B 31 01 0C 4F 15 BC 0D 01 F9 8C BA 01 00 D9 A9 40 01 0C 41 4C 31 01 0C EF B9 B8 0D 01 99 8A 40 01 0C 21 CA 8C 01 0C 01 AD 6F 01 0C 33 0B 5F 01 0C 99 67 31 01 0C 62 80 5F 01 0C CB 45 5F 01 0C 79 08 9C 01 0C F1 A5 40 01 0C E1 87 7D 01 0C BB 9B 5F 01 0C B1 86 40 01 0C 39 C6 8C 01 0C 7A 7C 5F 01 0C B2 63 31 01 0C 29 85 BA 01 0E 91 04 9C 01 0C 09 A2 40 01 0C 71 44 31 01 0C F9 83 7D 01 0C 1D A9 6F 01 0C D3 97 5F 01 0C C9 82 40 01 0C 51 C2 8C 01 0C 61 BD 40 01 0C C9 5F 31 01 0C 51 9F 7D 01 0C 92 78 5F 01 0C 0F 08 B9 0D 01 A9 00 9C 01 0C 89 40 31 01 0C 11 80 7D 01 0C 35 A5 6F 01 0C BB 1E 5F 01 0C 53 59 5F 01 0C E9 03 00 00 01 22 7B 31 01 0C EB 93 5F 01 0C EA 03 00 00 01 E1 7E 40 01 0C 69 BE 8C 01 0C 79 B9 40 01 0C E1 5B 31 01 0C EB 03 00 00 01 69 9B 7D 01 0C AA 74 5F 01 0C EC 03 00 00 01 ED 03 00 00 01 C1 FC 9B 01 0C EE 03 00 00 01".ToByteArray());
        // 0xF0, ResponsePet P(0F 01)
        // RequestFieldEnter
        //session.Send("16 00 00 41 75 19 03 00 01 8A 42 0F 00 00 00 00 00 00 C0 28 C4 00 40 03 44 00 00 16 44 00 00 00 00 00 00 00 00 55 FF 33 42 E8 49 01 00".ToByteArray());
        session.Send(RequestFieldEnterPacket.RequestEnter(session.Player.FieldPlayer));

        Party party = GameServer.PartyManager.GetPartyByMember(player.CharacterId);

        if (party != null)
        {
            player.Party = party;
            party.BroadcastPacketParty(PartyPacket.LoginNotice(player), session);
            session.Send(PartyPacket.Create(party, false));
        }

        // SendUgc: 15 01 00 00 00 00 00 00 00 00 00 00 00 4B 00 00 00
        // SendHomeCommand: 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00

        session.Player.TimeSyncLoop();
        session.Send(TimeSyncPacket.SetSessionServerTick(0));
        //session.Send("B9 00 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00".ToByteArray());
        session.Send(ServerEnterPacket.Confirm());

        //session.Send(0xF0, 0x00, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00);
        //session.Send(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
        //session.Send(ServerEnterPacket.Confirm());
    }