private static void HandleMarketItemPay(GameSession session, MeretMarketItem marketItem, int itemIndex, int totalQuantity) { switch (marketItem.TokenType) { case MeretMarketCurrencyType.Meret: if (!session.Player.Account.RemoveMerets(marketItem.SalePrice)) { return; } break; case MeretMarketCurrencyType.Meso: if (!session.Player.Wallet.Meso.Modify(marketItem.SalePrice)) { return; } break; } Item item = new Item(marketItem.ItemId) { Amount = marketItem.Quantity + marketItem.BonusQuantity, Rarity = marketItem.Rarity }; if (marketItem.Duration != 0) { item.ExpiryTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + Environment.TickCount + (marketItem.Duration * (24 * 60 * 60)); } InventoryController.Add(session, item, true); session.Send(MeretMarketPacket.Purchase(marketItem, itemIndex, totalQuantity)); }
private static void PurchaseUgcItem(GameSession session, long ugcMarketItemId) { UgcMarketItem marketItem = GameServer.UgcMarketManager.FindItemById(ugcMarketItemId); if (marketItem is null || marketItem.ListingExpirationTimestamp < TimeInfo.Now()) { return; } if (!HandleMarketItemPay(session, marketItem.Price, MeretMarketCurrencyType.Meret)) { return; } marketItem.SalesCount++; DatabaseManager.UgcMarketItems.Update(marketItem); _ = new UgcMarketSale(marketItem.Price, marketItem.Item.Ugc.Name, marketItem.SellerCharacterId); Item item = new(marketItem.Item) { CreationTime = TimeInfo.Now() }; item.Uid = DatabaseManager.Items.Insert(item); session.Player.Inventory.AddItem(session, item, true); session.Send(MeretMarketPacket.Purchase(0, marketItem.MarketId, marketItem.Price, 1)); }
private static void HandleRelistItem(GameSession session, PacketReader packet) { long ugcMarketItemId = packet.ReadLong(); long price = packet.ReadLong(); bool promote = packet.ReadBool(); List <string> tags = packet.ReadUnicodeString().Split(",").ToList(); string description = packet.ReadUnicodeString(); long listingFee = packet.ReadLong(); UgcMarketItem item = GameServer.UgcMarketManager.FindItemById(ugcMarketItemId); if (item is null || item.SellerCharacterId != session.Player.CharacterId || item.ListingExpirationTimestamp < TimeInfo.Now()) { return; } long totalFee = GetListingFee(session.Player.CharacterId, promote); if (!HandleMarketItemPay(session, totalFee, MeretMarketCurrencyType.Meret)) { return; } item.Price = price; item.ListingExpirationTimestamp = long.Parse(ConstantsMetadataStorage.GetConstant("UGCShopSaleDay")) * 86400 + TimeInfo.Now(); if (promote) { item.PromotionExpirationTimestamp = long.Parse(ConstantsMetadataStorage.GetConstant("UGCShopAdHour")) * 3600 + item.ListingExpirationTimestamp; } item.Status = UgcMarketListingStatus.Active; item.Description = description; item.Tags = tags; DatabaseManager.UgcMarketItems.Update(item); session.Send(MeretMarketPacket.RelistItem(item)); }
private static void HandleOpenUGCMarket(GameSession session, PacketReader packet, MeretMarketCategoryMetadata metadata) { GenderFlag gender = (GenderFlag)packet.ReadByte(); JobFlag job = (JobFlag)packet.ReadInt(); short sortBy = packet.ReadByte(); List <UGCMarketItem> items = GameServer.UGCMarketManager.FindItemsByCategory(metadata.ItemCategories, gender, job, sortBy); session.Send(MeretMarketPacket.LoadUGCShopCategory(items)); }
private static void HandleOpenPremiumMarket(GameSession session, MeretMarketCategory category) { List <MeretMarketItem> marketItems = DatabaseManager.MeretMarket.FindAllByCategoryId((category)); if (marketItems is null) { return; } session.Send(MeretMarketPacket.LoadPremiumShopCategory(marketItems)); }
private static void HandleHome(GameSession session) { List <MeretMarketItem> marketItems = DatabaseManager.MeretMarket.FindAllByCategoryId(MeretMarketCategory.Promo); if (marketItems == null) { return; } session.Send(MeretMarketPacket.Promos(marketItems)); }
private static void HandleHome(GameSession session) { List <MeretMarketMetadata> marketItems = MeretMarketMetadataStorage.GetCategoryItems(MeretMarketCategory.Promo); if (marketItems == null) { return; } session.Send(MeretMarketPacket.Promos(marketItems)); }
private static void HandleOpenPremium(GameSession session, PacketReader packet) { MeretMarketCategory category = (MeretMarketCategory)packet.ReadInt(); List <MeretMarketMetadata> marketItems = MeretMarketMetadataStorage.GetCategoryItems(category); if (marketItems == null) { return; } session.Send(MeretMarketPacket.Premium(marketItems)); }
private static void HandleOpenPremium(GameSession session, PacketReader packet) { MeretMarketCategory category = (MeretMarketCategory)packet.ReadInt(); List <MeretMarketItem> marketItems = DatabaseManager.MeretMarket.FindAllByCategoryId(category); if (marketItems == null) { return; } session.Send(MeretMarketPacket.Premium(marketItems)); }
private static void HandleSendMarketRequest(GameSession session, PacketReader packet) { packet.ReadByte(); //constant 1 int meretMarketItemUid = packet.ReadInt(); List <MeretMarketItem> meretMarketItems = new() { DatabaseManager.MeretMarket.FindById(meretMarketItemUid) }; session.Send(MeretMarketPacket.Premium(meretMarketItems)); } }
private static void HandleLoadPersonalListings(GameSession session) { List <UGCMarketItem> items = GameServer.UGCMarketManager.GetItemsByCharacterId(session.Player.CharacterId); // TODO: Possibly a better way to implement updating item status? foreach (UGCMarketItem item in items) { if (item.ListingExpirationTimestamp < TimeInfo.Now() && item.Status == UGCMarketListingStatus.Active) { item.Status = UGCMarketListingStatus.Expired; DatabaseManager.UGCMarketItems.Update(item); } } session.Send(MeretMarketPacket.LoadPersonalListings(items)); }
private static void HandleListItem(GameSession session, PacketReader packet) { long itemUid = packet.ReadLong(); long salePrice = packet.ReadLong(); bool promote = packet.ReadBool(); List <string> tags = packet.ReadUnicodeString().Split(",").ToList(); string description = packet.ReadUnicodeString(); long listingFee = packet.ReadLong(); Item item = null; if (session.Player.Inventory.HasItem(itemUid)) { item = session.Player.Inventory.GetByUid(itemUid); } else if (session.Player.Account.Home.WarehouseInventory.ContainsKey(itemUid)) { item = session.Player.Account.Home.WarehouseInventory[itemUid]; } if (item is null) { return; } if (item.Ugc is null || item.Ugc.CharacterId != session.Player.CharacterId || ItemMetadataStorage.GetLimitMetadata(item.Id).MeretMarketListable) { return; } if (salePrice < item.Ugc.SalePrice || salePrice > long.Parse(ConstantsMetadataStorage.GetConstant("UGCShopSellMaxPrice"))) { return; } long totalFee = GetListingFee(session.Player.CharacterId, promote); if (!HandleMarketItemPay(session, totalFee, MeretMarketCurrencyType.Meret)) { return; } UgcMarketItem marketItem = new(item, salePrice, session.Player, tags, description, promote); session.Send(MeretMarketPacket.ListItem(marketItem)); session.Send(MeretMarketPacket.UpdateExpiration(marketItem)); }
private static void PurchasePremiumItem(GameSession session, PacketReader packet, int marketItemId) { packet.ReadInt(); int childMarketItemId = packet.ReadInt(); long unk2 = packet.ReadLong(); int itemIndex = packet.ReadInt(); int totalQuantity = packet.ReadInt(); int unk3 = packet.ReadInt(); byte unk4 = packet.ReadByte(); string unk5 = packet.ReadUnicodeString(); string unk6 = packet.ReadUnicodeString(); long price = packet.ReadLong(); MeretMarketItem marketItem = DatabaseManager.MeretMarket.FindById(marketItemId); if (marketItem is null) { return; } if (childMarketItemId != 0) { marketItem = marketItem.AdditionalQuantities.FirstOrDefault(x => x.MarketId == childMarketItemId); if (marketItem is null) { return; } } if (!HandleMarketItemPay(session, marketItem.Price, marketItem.TokenType)) { return; } Item item = new(marketItem.ItemId) { Amount = marketItem.Quantity + marketItem.BonusQuantity, Rarity = marketItem.Rarity }; if (marketItem.Duration != 0) { item.ExpiryTime = TimeInfo.Now() + Environment.TickCount + marketItem.Duration * 24 * 60 * 60; } session.Player.Inventory.AddItem(session, item, true); session.Send(MeretMarketPacket.Purchase(marketItem.MarketId, 0, marketItem.Price, totalQuantity, itemIndex)); }
private static void HandleRemoveListing(GameSession session, PacketReader packet) { packet.ReadInt(); // 0 long ugcMarketItemId = packet.ReadLong(); packet.ReadLong(); // duplicate id read? UgcMarketItem item = GameServer.UgcMarketManager.FindItemById(ugcMarketItemId); if (item is null || item.SellerCharacterId != session.Player.CharacterId) { return; } session.Send(MeretMarketPacket.RemoveListing(item.MarketId)); DatabaseManager.UgcMarketItems.Delete(item.MarketId); GameServer.UgcMarketManager.RemoveListing(item); }
private static void HandleOpenShop(GameSession session, PacketReader packet) { MeretMarketCategory category = (MeretMarketCategory)packet.ReadInt(); GenderFlag gender = (GenderFlag)packet.ReadByte(); JobFlag job = (JobFlag)packet.ReadInt(); MeretMarketSort sortBy = (MeretMarketSort)packet.ReadByte(); string searchString = packet.ReadUnicodeString(); int startPage = packet.ReadInt(); packet.ReadInt(); // repeat page? MeretMarketSection section = ReadMarketSection(packet.ReadByte()); packet.ReadByte(); byte itemsPerPage = packet.ReadByte(); MeretMarketTab metadata = MeretMarketCategoryMetadataStorage.GetTabMetadata(section, (int)category); if (metadata is null) { return; } List <MeretMarketItem> items = new(); switch (section) { case MeretMarketSection.UgcMarket: items.AddRange(GameServer.UgcMarketManager.FindItems(metadata.ItemCategories, gender, job, searchString)); break; case MeretMarketSection.PremiumMarket: case MeretMarketSection.RedMeretMarket: items.AddRange(DatabaseManager.MeretMarket.FindAllByCategory(section, category, gender, job, searchString)); break; } int totalItems = items.Count; items = MeretMarketHelper.MarketItemsSorted(items, sortBy); items = MeretMarketHelper.TakeLimit(items, startPage, itemsPerPage); session.Send(MeretMarketPacket.LoadShopCategory(items, totalItems)); }
private static void HandleUnlistItem(GameSession session, PacketReader packet) { packet.ReadInt(); // 0 long ugcMarketItemId = packet.ReadLong(); packet.ReadLong(); // duplicate id read? UgcMarketItem item = GameServer.UgcMarketManager.FindItemById(ugcMarketItemId); if (item is null || item.SellerCharacterId != session.Player.CharacterId) { return; } item.ListingExpirationTimestamp = long.Parse(ConstantsMetadataStorage.GetConstant("UGCShopExpiredListingRemovalHour")) * 3600 + TimeInfo.Now(); item.PromotionExpirationTimestamp = 0; item.Status = UgcMarketListingStatus.Expired; DatabaseManager.UgcMarketItems.Update(item); session.Send(MeretMarketPacket.UpdateExpiration(item)); }
private static void HandleListItem(GameSession session, PacketReader packet) { long itemUid = packet.ReadLong(); long salePrice = packet.ReadLong(); bool promote = packet.ReadBool(); List <string> tags = packet.ReadUnicodeString().Split(",").ToList(); string description = packet.ReadUnicodeString(); long listingFee = packet.ReadLong(); // TODO: Check if item is a ugc block and not an item. Find item from their block inventory if (!session.Player.Inventory.Items.ContainsKey(itemUid)) { return; } Item item = session.Player.Inventory.Items[itemUid]; if (item.UGC is null || item.UGC.CharacterId != session.Player.CharacterId) { return; } if (salePrice < item.UGC.SalePrice || salePrice > long.Parse(ConstantsMetadataStorage.GetConstant("UGCShopSellMaxPrice"))) { return; } long totalFee = GetListingFee(session.Player.CharacterId, promote); if (!HandleMarketItemPay(session, totalFee, MeretMarketCurrencyType.Meret)) { return; } UGCMarketItem marketItem = new(item, salePrice, session.Player, tags, description, promote); session.Send(MeretMarketPacket.ListItem(marketItem)); session.Send(MeretMarketPacket.UpdateExpiration(marketItem)); }
private static void HandleCollectProfit(GameSession session, PacketReader packet) { long saleId = packet.ReadLong(); List <UgcMarketSale> sales = GameServer.UgcMarketManager.GetSalesByCharacterId(session.Player.CharacterId); long profitDelayTime = long.Parse(ConstantsMetadataStorage.GetConstant("UGCShopProfitDelayInDays")); long totalProfit = 0; foreach (UgcMarketSale sale in sales) { if (!(sale.SoldTimestamp + profitDelayTime < TimeInfo.Now())) { continue; } totalProfit += sale.Profit; GameServer.UgcMarketManager.RemoveSale(sale); DatabaseManager.UgcMarketSales.Delete(saleId); } session.Player.Account.GameMeret.Modify(totalProfit); session.Send(MeretsPacket.UpdateMerets(session.Player.Account, totalProfit)); session.Send(MeretMarketPacket.UpdateProfit(saleId)); }
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); }
private static void HandleLoadSales(GameSession session) { List <UGCMarketSale> sales = GameServer.UGCMarketManager.GetSalesByCharacterId(session.Player.CharacterId); session.Send(MeretMarketPacket.LoadSales(sales)); }
private static void HandleInitialize(GameSession session) { session.Send(MeretMarketPacket.Initialize()); }
private static void HandleLoadCart(GameSession session) { session.Send(MeretMarketPacket.LoadCart()); }
private static void PurchasePremiumItem(GameSession session, PacketReader packet, int marketItemId) { packet.ReadInt(); int childMarketItemId = packet.ReadInt(); long unk2 = packet.ReadLong(); int itemIndex = packet.ReadInt(); int totalQuantity = packet.ReadInt(); int unk3 = packet.ReadInt(); byte unk4 = packet.ReadByte(); string unk5 = packet.ReadUnicodeString(); string unk6 = packet.ReadUnicodeString(); long price = packet.ReadLong(); PremiumMarketItem marketItem = DatabaseManager.MeretMarket.FindById(marketItemId); if (marketItem is null) { return; } if (childMarketItemId != 0) { marketItem = marketItem.AdditionalQuantities.FirstOrDefault(x => x.MarketId == childMarketItemId); if (marketItem is null) { return; } } long itemPrice = marketItem.Price; if (marketItem.SalePrice != 0) { itemPrice = marketItem.SalePrice; } if (!HandleMarketItemPay(session, itemPrice, marketItem.TokenType)) { SystemNotice noticeId = SystemNotice.EmptyString; switch (marketItem.TokenType) { case MeretMarketCurrencyType.Meso: noticeId = SystemNotice.ErrorInsufficientMeso; break; case MeretMarketCurrencyType.Meret: noticeId = SystemNotice.ErrorInsufficientMeret; break; case MeretMarketCurrencyType.RedMeret: noticeId = SystemNotice.ErrorInsufficientMeretRed; break; } session.Send(NoticePacket.Notice(noticeId, NoticeType.Popup)); return; } Item item = new(marketItem.ItemId, marketItem.Quantity + marketItem.BonusQuantity, marketItem.Rarity); if (marketItem.Duration != 0) { item.ExpiryTime = TimeInfo.Now() + Environment.TickCount + marketItem.Duration * 24 * 60 * 60; } session.Player.Inventory.AddItem(session, item, true); session.Send(MeretMarketPacket.Purchase((int)marketItem.MarketId, 0, marketItem.Price, totalQuantity, itemIndex)); }