From f5ea82f7358bd0b8f5187343c3dcc3e0fb1d4adc Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Sun, 10 Dec 2017 13:38:53 -0500 Subject: [PATCH] Added the UpdateItemPackage packet used to signal the server to send bazaar item info. Added a transaction method in WorldManager. Fixed some inventory bugs. InvItems now track what player, itempackage, and itemslot they are in... and may have their quantity set from there. Fixed DB SetQuantity bug. --- FFXIVClassic Map Server/Database.cs | 42 ++-------------- .../FFXIVClassic Map Server.csproj | 1 + FFXIVClassic Map Server/PacketProcessor.cs | 6 +++ FFXIVClassic Map Server/WorldManager.cs | 31 ++++++++++++ .../actors/chara/Character.cs | 12 ++++- .../actors/chara/player/Player.cs | 37 ++++++++++---- .../dataobjects/InventoryItem.cs | 49 +++++++++++++++++-- .../receive/UpdateItemPackagePacket.cs | 29 +++++++++++ 8 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 FFXIVClassic Map Server/packets/receive/UpdateItemPackagePacket.cs diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index f345256f..f8ef5398 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -1698,7 +1698,9 @@ namespace FFXIVClassic_Map_Server } } - public static void SetQuantity(Player player, ulong serverItemId, int quantity) + + + public static void SetQuantity(ulong serverItemId, int quantity) { using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) { @@ -1707,13 +1709,12 @@ namespace FFXIVClassic_Map_Server conn.Open(); string query = @" - UPDATE characters_inventory + UPDATE server_items SET quantity = @quantity - WHERE characterId = @charId and serverItemId = @serverItemId; + WHERE id = @serverItemId; "; MySqlCommand cmd = new MySqlCommand(query, conn); - cmd.Parameters.AddWithValue("@charId", player.actorId); cmd.Parameters.AddWithValue("@serverItemId", serverItemId); cmd.Parameters.AddWithValue("@quantity", quantity); cmd.ExecuteNonQuery(); @@ -1796,39 +1797,6 @@ namespace FFXIVClassic_Map_Server } } - public static void SetQuantity(Retainer retainer, ulong serverItemId, int quantity) - { - using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) - { - try - { - conn.Open(); - - string query = @" - UPDATE retainers_inventory - SET quantity = @quantity - WHERE retainerId = @retainerId and serverItemId = @serverItemId; - "; - - MySqlCommand cmd = new MySqlCommand(query, conn); - cmd.Parameters.AddWithValue("@retainerId", retainer.getRetainerId()); - cmd.Parameters.AddWithValue("@serverItemId", serverItemId); - cmd.Parameters.AddWithValue("@quantity", quantity); - cmd.ExecuteNonQuery(); - - } - catch (MySqlException e) - { - Program.Log.Error(e.ToString()); - } - finally - { - conn.Dispose(); - } - } - - } - public static void RemoveItem(Retainer retainer, ulong serverItemId) { using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}; Allow User Variables=True", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 3febcfd7..7f5f9e68 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -146,6 +146,7 @@ + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index ed297041..829c1b0d 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -240,6 +240,12 @@ namespace FFXIVClassic_Map_Server if (paramRequest.paramName.Equals("charaWork/exp")) session.GetActor().SendCharaExpInfo(); break; + //Item Package Request + case 0x0131: + UpdateItemPackagePacket packageRequest = new UpdateItemPackagePacket(subpacket.data); + if (Server.GetWorldManager().GetPCInWorld(packageRequest.actorID) != null) + Server.GetWorldManager().GetPCInWorld(packageRequest.actorID).SendItemPackage(session.GetActor(), packageRequest.packageId); + break; //Group Created Confirm case 0x0133: GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data); diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 7434f6ca..daba1e69 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -1049,6 +1049,33 @@ namespace FFXIVClassic_Map_Server return Database.CreateItem(itemId, amount, quality, modifiers); } + public bool BazaarPurchaseOperation(Player bazaar, Player buyer, InventoryItem itemToBuy, int quantity, int cost) + { + if (bazaar == null || buyer == null || itemToBuy == null) + return false; + + if (quantity <= 0) + return false; + + if (cost < 0) + return false; + + if (itemToBuy.GetBazaarMode() == InventoryItem.TYPE_STACK) + { + itemToBuy.ChangeQuantity(-quantity); + buyer.AddItemStack(itemToBuy.itemId, quantity, itemToBuy.quality); + buyer.GetItemPackage(Inventory.CURRENCY_CRYSTALS).RemoveItem(1000001, cost); + } + else + { + itemToBuy.ChangeQuantity(-quantity); + buyer.AddItem(itemToBuy.itemId, quantity, itemToBuy.quality); + buyer.GetItemPackage(Inventory.CURRENCY_CRYSTALS).RemoveItem(1000001, cost); + } + + return true; + } + public void AddToBazaar(Player player, InventoryItem reward, InventoryItem seek, int rewardAmount, int seekAmount, byte bazaarMode) { bool succ = false; @@ -1079,6 +1106,8 @@ namespace FFXIVClassic_Map_Server } } + + player.CheckBazaarFlags(); } @@ -1106,6 +1135,8 @@ namespace FFXIVClassic_Map_Server seekRef.SetNormal(); player.AddItem(seekRef); } + + player.CheckBazaarFlags(); } /* public void TransactionBazaar(Player owner, Player other, InventoryItem reward, InventoryItem seek, int rewardAmount, int seekAmount) diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index e9a08c74..3e0c1cb8 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -145,6 +145,16 @@ namespace FFXIVClassic_Map_Server.Actors } } + public void AddItemStack(uint catalogID, int quantity, byte quality) + { + ItemData itemData = Server.GetItemGamedata(catalogID); + if (itemData != null) + { + int totalQuantity = itemData.maxStack * quantity; + AddItem(catalogID, totalQuantity, quality); + } + } + public void AddItem(InventoryItem item) { ushort itemPackage = GetPackageForItem(item.GetItemData().catalogID); @@ -228,7 +238,7 @@ namespace FFXIVClassic_Map_Server.Actors ushort itemPackage = GetPackageForItem(catalogID); if (itemPackages.ContainsKey(itemPackage)) { - itemPackages[itemPackage].HasItem(catalogID, minQuantity, quality); + return itemPackages[itemPackage].HasItem(catalogID, minQuantity, quality); } return false; } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 9f362fc2..f38dd81c 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -139,9 +139,6 @@ namespace FFXIVClassic_Map_Server.Actors //Nameplate Stuff public uint currentLSPlate = 0; - public bool isBazaarRetail = false; - public bool isBazaarRepair = false; - public bool isMateriaRequest = false; public byte repairType = 0; //Retainer @@ -505,6 +502,7 @@ namespace FFXIVClassic_Map_Server.Actors } //Bazaar + CheckBazaarFlags(true); if (charaWork.eventSave.repairType != 0) propPacketUtil.AddProperty("charaWork.eventSave.repairType"); if (charaWork.eventTemp.bazaarRetail) @@ -1067,7 +1065,7 @@ namespace FFXIVClassic_Map_Server.Actors QueuePackets(propPacketUtil.Done()); } - public void CheckBazaarFlags() + public void CheckBazaarFlags(bool noUpdate = false) { bool isDealing = false, isRepairing = false, seekingItem = false; lock (GetItemPackage(Inventory.BAZAAR)) @@ -1089,15 +1087,26 @@ namespace FFXIVClassic_Map_Server.Actors } } + bool doUpdate = false; + + if (charaWork.eventTemp.bazaarRetail != isDealing || charaWork.eventTemp.bazaarRepair != isRepairing || charaWork.eventTemp.bazaarMateria != (GetItemPackage(Inventory.MELDREQUEST).GetCount() != 0)) + doUpdate = true; + charaWork.eventTemp.bazaarRetail = isDealing; charaWork.eventTemp.bazaarRepair = isRepairing; charaWork.eventTemp.bazaarMateria = GetItemPackage(Inventory.MELDREQUEST).GetCount() == 0; - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/bazaar", this); - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRetail"); - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRepair"); - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarMateria"); - QueuePackets(propPacketUtil.Done()); + if (noUpdate) + return; + + if (doUpdate) + { + ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/bazaar", this); + propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRetail"); + propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRepair"); + propPacketUtil.AddProperty("charaWork.eventTemp.bazaarMateria"); + QueuePackets(propPacketUtil.Done()); + } } public int GetCurrentGil() @@ -1808,6 +1817,16 @@ namespace FFXIVClassic_Map_Server.Actors chocoboAppearance = appearanceId; } + public void SendItemPackage(Player player, uint id) + { + if (!itemPackages.ContainsKey((ushort)id)) + return; + + player.QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId)); + itemPackages[(ushort)id].SendFullInventory(player); + player.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); + } + public Retainer SpawnMyRetainer(Npc bell, int retainerIndex) { Retainer retainer = Database.LoadRetainer(this, retainerIndex); diff --git a/FFXIVClassic Map Server/dataobjects/InventoryItem.cs b/FFXIVClassic Map Server/dataobjects/InventoryItem.cs index 5ce9f0d9..50d570a0 100644 --- a/FFXIVClassic Map Server/dataobjects/InventoryItem.cs +++ b/FFXIVClassic Map Server/dataobjects/InventoryItem.cs @@ -1,4 +1,5 @@ -using System; +using FFXIVClassic_Map_Server.Actors; +using System; using System.IO; namespace FFXIVClassic_Map_Server.dataobjects @@ -39,6 +40,7 @@ namespace FFXIVClassic_Map_Server.dataobjects public ItemModifier modifiers; public readonly ItemData itemData; + public Character owner = null; public ushort slot = 0xFFFF; public ushort itemPackage = 0xFFFF; @@ -197,10 +199,49 @@ namespace FFXIVClassic_Map_Server.dataobjects return data; } - public void RefreshPositioning(ushort itemPackage, ushort slot) + public void SetQuantity(uint quantity) { - this.itemPackage = itemPackage; - this.slot = slot; + lock (owner.GetItemPackage(itemPackage)) + { + this.quantity = (int)quantity; + if (quantity < 0) + quantity = 0; + Database.SetQuantity(uniqueId, this.quantity); + + if (owner != null && owner is Player) + owner.GetItemPackage(itemPackage).RefreshItem((Player)owner, this); + } + } + + public void ChangeQuantity(int quantityDelta) + { + lock (owner.GetItemPackage(itemPackage)) + { + this.quantity += quantityDelta; + if (quantity < 0) + quantity = 0; + + if (quantity == 0) + { + owner.RemoveItem(this); + return; + } + + Database.SetQuantity(uniqueId, this.quantity); + + if (owner != null && owner is Player) + owner.GetItemPackage(itemPackage).RefreshItem((Player)owner, this); + } + } + + public void RefreshPositioning(Character owner, ushort itemPackage, ushort slot) + { + lock (owner.GetItemPackage(itemPackage)) + { + this.owner = owner; + this.itemPackage = itemPackage; + this.slot = slot; + } } public void SetExclusive(bool isExclusive) diff --git a/FFXIVClassic Map Server/packets/receive/UpdateItemPackagePacket.cs b/FFXIVClassic Map Server/packets/receive/UpdateItemPackagePacket.cs new file mode 100644 index 00000000..2f863013 --- /dev/null +++ b/FFXIVClassic Map Server/packets/receive/UpdateItemPackagePacket.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; + +namespace FFXIVClassic_Map_Server.packets.receive +{ + class UpdateItemPackagePacket + { + public bool invalidPacket = false; + public uint actorID; + public uint packageId; + + public UpdateItemPackagePacket(byte[] data) + { + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try{ + actorID = binReader.ReadUInt32(); + packageId = binReader.ReadUInt32(); + } + catch (Exception){ + invalidPacket = true; + } + } + } + } + } +}