using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using WingsEmu.Game._i18n; using WingsEmu.Game.Characters.Events; using WingsEmu.Game.Extensions; using WingsEmu.Game.Inventory; using WingsEmu.Game.Networking; using WingsEmu.Game.Shops; using WingsEmu.Game.Shops.Event; using WingsEmu.Packets.ClientPackets; using WingsEmu.Packets.Enums; using WingsEmu.Packets.Enums.Chat; namespace WingsEmu.Plugins.PacketHandling.Game.Npc; public class MShopPacketHandler : GenericGamePacketHandlerBase { private readonly IGameLanguageService _language; public MShopPacketHandler(IGameLanguageService language) => _language = language; protected override async Task HandlePacketAsync(IClientSession session, MShopPacket packet) { if (session.IsActionForbidden()) { return; } switch (packet.Type) { case MShopPacketType.CloseShop: await session.EmitEventAsync(new ShopPlayerCloseEvent()); break; case MShopPacketType.OpenDialog: session.SendPacket("ishop"); break; case MShopPacketType.OpenShop: await ProcessPacketStructure(session, packet.PacketData); break; default: return; } } private async Task ProcessPacketStructure(IClientSession session, string packet) { string[] packetsplit = packet.Split(' '); if (packetsplit.Length <= 80) { return; } if (!session.HasCurrentMapInstance || session.PlayerEntity.HasShopOpened || session.PlayerEntity.IsInExchange()) { return; } var list = new List(); const int amountPersonalShopItems = 20; int nonNullItemsCount = 0; for (short i = 0; i < amountPersonalShopItems; i++) { int packetIndexGuide = i * 4; if (!(Enum.TryParse(packetsplit[packetIndexGuide], out InventoryType inventoryType) && short.TryParse(packetsplit[packetIndexGuide + 1], out short inventorySlot) && short.TryParse(packetsplit[packetIndexGuide + 2], out short sellAmount) && long.TryParse(packetsplit[packetIndexGuide + 3], out long price))) { list.Add(null); continue; } if (inventorySlot < 0 || sellAmount < 1 || price < 1) { list.Add(null); continue; } if (inventoryType != InventoryType.Equipment && inventoryType != InventoryType.Etc && inventoryType != InventoryType.Main) { await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, $"[PLAYER_SHOP_OPEN] Tried to add an object from a non allowed InventoryType. InventoryType: '{inventoryType.ToString()}'"); return; } InventoryItem inv = session.PlayerEntity.GetItemBySlotAndType(inventorySlot, inventoryType); if (inv == null || inv.ItemInstance.Amount < sellAmount) { await session.NotifyStrangeBehavior(StrangeBehaviorSeverity.ABUSING, "[PLAYER_SHOP_OPEN] Tried to add a nonexistent object."); return; } if (!inv.ItemInstance.GameItem.IsTradable || inv.ItemInstance.IsBound) { session.SendChatMessage(_language.GetLanguage(GameDialogKey.SHOP_CHATMESSAGE_ONLY_TRADABLE_ITEMS, session.UserLanguage), ChatMessageColorType.Yellow); session.SendShopEndPacket(ShopEndType.Player); return; } list.Add(new ShopPlayerItem { ShopSlot = i, PricePerUnit = price, InventoryItem = inv, SellAmount = sellAmount }); nonNullItemsCount++; } if (nonNullItemsCount < 1) { session.SendShopEndPacket(ShopEndType.Player); session.SendChatMessage(_language.GetLanguage(GameDialogKey.SHOP_CHATMESSAGE_EMPTY, session.UserLanguage), ChatMessageColorType.Yellow); return; } var shopNameBuilder = new StringBuilder(); const int maxShopNameLength = 20; for (int j = 80; j < packetsplit.Length; j++) { if (maxShopNameLength < shopNameBuilder.Length) { break; } shopNameBuilder.Append(packetsplit[j]); shopNameBuilder.Append(' '); } string shopName = shopNameBuilder.ToString(0, maxShopNameLength < shopNameBuilder.Length ? maxShopNameLength : shopNameBuilder.Length); if (string.IsNullOrWhiteSpace(shopName) || string.IsNullOrEmpty(shopName)) { shopName = _language.GetLanguageFormat(GameDialogKey.SHOP_DEFAULT_NAME, session.UserLanguage, session.PlayerEntity.Name); } await session.EmitEventAsync(new ShopPlayerOpenEvent { Items = list, ShopTitle = shopName }); } }