From 69d4b19979dbd994c2f10f73d83c6cbabf20b683 Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Tue, 4 Jun 2019 00:11:36 -0400 Subject: [PATCH] More inventory fixing after I broke it. Added preliminary final trade code. Moved recalc stats to the end of equipcommand, not on every modification of the referred item package. --- FFXIVClassic Map Server/Database.cs | 11 +- FFXIVClassic Map Server/WorldManager.cs | 150 ++++++++++++- .../actors/chara/ItemPackage.cs | 199 +++++++++++++++--- .../actors/chara/ReferencedItemPackage.cs | 121 ++++------- .../actors/chara/player/Player.cs | 2 +- .../dataobjects/InventoryItem.cs | 26 +-- .../inventory/LinkedItemListX01Packet.cs | 25 +-- .../inventory/LinkedItemListX08Packet.cs | 5 +- .../inventory/LinkedItemListX16Packet.cs | 5 +- .../inventory/LinkedItemListX32Packet.cs | 5 +- .../inventory/LinkedItemListX64Packet.cs | 5 +- data/scripts/commands/EquipCommand.lua | 2 + data/scripts/commands/TradeExecuteCommand.lua | 2 +- 13 files changed, 388 insertions(+), 170 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 96877f0e..85db572b 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -1131,13 +1131,10 @@ namespace FFXIVClassic_Map_Server } - public static uint[] GetEquipment(Player player, ushort classId) + public static InventoryItem[] GetEquipment(Player player, ushort classId) { - uint[] equipment = new uint[player.GetEquipment().GetCapacity()]; - - for (int i = 0; i < equipment.Length; i++) - equipment[i] = 0xFFFFFFFF; - + InventoryItem[] equipment = new InventoryItem[player.GetEquipment().GetCapacity()]; + 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 @@ -1162,7 +1159,7 @@ namespace FFXIVClassic_Map_Server ushort equipSlot = reader.GetUInt16(0); ulong uniqueItemId = reader.GetUInt16(1); InventoryItem item = player.GetItemPackage(ItemPackage.NORMAL).GetItemByUniqueId(uniqueItemId); - equipment[equipSlot] = (uint)((item.itemPackage << 16) | item.slot); + equipment[equipSlot] = item; } } } diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index e1b6de5d..cea08c80 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -1362,18 +1362,152 @@ namespace FFXIVClassic_Map_Server DeleteTradeGroup(group.groupIndex); } - public void SwapTradedItems(Player p1, Player p2) + public void CompleteTrade(Player p1, Player p2) { - lock (tradeLock) - { - if (p1.IsTradeAccepted() && p2.IsTradeAccepted()) - { - //move items around + if (!p1.IsTradeAccepted() || !p2.IsTradeAccepted()) + return; - p1.FinishTradeTransaction(); - p2.FinishTradeTransaction(); + TradeGroup group = GetTradeGroup(p1.actorId); + + if (group == null) + { + p1.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!"); + return; + } + + ReferencedItemPackage p1Offer = p1.GetTradeOfferings(); + ReferencedItemPackage p2Offer = p2.GetTradeOfferings(); + + int failCode = 0; + Player failurePlayerOffer = null; + Player failureCauser = null; + + //TODO Add full inventory check + + //Check items. If there is a failcode abort and set. + for (ushort i = 0; i < p1Offer.GetCapacity(); i++) + { + InventoryItem p1ItemToP2 = p1Offer.GetItemAtSlot(i); + InventoryItem p2ItemToP1 = p2Offer.GetItemAtSlot(i); + + int failCodeP1 = CheckIfCanTrade(p1, p2, p1ItemToP2); //P2's inv caused a failcode for P1 + int failCodeP2 = CheckIfCanTrade(p2, p1, p2ItemToP1); //P1's inv caused a failcode for P2 + + if (failCodeP1 != 0) + { + failCode = failCodeP1; + failurePlayerOffer = p1; + failureCauser = p2; + break; + } + + if (failCodeP2 != 0) + { + failCode = failCodeP2; + failurePlayerOffer = p2; + failureCauser = p1; + break; } } + + //Do we have a failcode? + switch (failCode) + { + case 1: + failurePlayerOffer.SendGameMessage(GetActor(), 25100, 0x20, (object)failureCauser); //Transaction failed. X inventory is either full or X can only hold one of the selected items. + failureCauser.SendGameMessage(GetActor(), 25100, 0x20, (object)failureCauser); //Transaction failed. X inventory is either full or X can only hold one of the selected items. + break; + case 2: + failurePlayerOffer.SendGameMessage(GetActor(), 25100, 0x20, (object)failureCauser); //Transaction failed. X inventory is either full or X can only hold one of the selected items. + failureCauser.SendGameMessage(GetActor(), 25103, 0x20); //Unable to complete transaction. You can only hold one of the selected items. + break; + case 3: + failurePlayerOffer.SendGameMessage(GetActor(), 25099, 0x20); //Unable to complete transaction. + failureCauser.SendGameMessage(GetActor(), 25104, 0x20); //Unable to complete transaction. You cannot receive the incoming payment. + break; + } + + //If all good, perform the swap. + if (failCode == 0) + { + lock (tradeLock) + { + for (ushort i = 0; i < p1Offer.GetCapacity(); i++) + { + InventoryItem p1ItemToP2 = p1Offer.GetItemAtSlot(i); + InventoryItem p2ItemToP1 = p2Offer.GetItemAtSlot(i); + + + //Transfer P1 -> P2 + if (p1ItemToP2 != null) + { + /* + if (p1ItemToP2.GetItemData().maxStack > 1) + { + p1.GetItemPackage(p1ItemToP2.itemPackage).RemoveItem(p1ItemToP2.itemId, p1ItemToP2.GetTradeQuantity(), p1ItemToP2.quality); + p2.GetItemPackage(p1ItemToP2.itemPackage).AddItem(p1ItemToP2.itemId, p1ItemToP2.GetTradeQuantity(), p1ItemToP2.quality); + } + else + { + p1.GetItemPackage(p1ItemToP2.itemPackage).RemoveItem(p1ItemToP2); + p2.GetItemPackage(p1ItemToP2.itemPackage).AddItem(p1ItemToP2); + } + */ + } + + //Transfer P2 -> P1 + if (p2ItemToP1 != null) + { + + /* + if (p2ItemToP1.GetItemData().maxStack > 1) + { + p2.GetItemPackage(p2ItemToP1.itemPackage).RemoveItem(p2ItemToP1.itemId, p2ItemToP1.GetTradeQuantity(), p2ItemToP1.quality); + p1.GetItemPackage(p2ItemToP1.itemPackage).AddItem(p2ItemToP1.itemId, p2ItemToP1.GetTradeQuantity(), p2ItemToP1.quality); + } + else + { + p2.GetItemPackage(p2ItemToP1.itemPackage).RemoveItem(p2ItemToP1); + p1.GetItemPackage(p2ItemToP1.itemPackage).AddItem(p2ItemToP1); + } + */ + } + + } + } + + p1.SendGameMessage(GetActor(), 25039, 0x20); //The trade is complete. + p2.SendGameMessage(GetActor(), 25039, 0x20); //The trade is complete. + } + + //Cleanup the trade and delete the tradegroup. + p1.FinishTradeTransaction(); + p2.FinishTradeTransaction(); + DeleteTradeGroup(group.groupIndex); + } + + private int CheckIfCanTrade(Player itemOwner, Player itemReceiver, InventoryItem item) + { + if (item == null) + return 0; + + //Check if their inventory can't hold all these things + if (false) + { + return 1; + } + //Check if they already have a unique + else if (item.GetItemData().isRare && itemReceiver.HasItem(item.itemId)) + { + return 2; + } + //Check if gil is max + else if (item.itemId == 100001 && item.dealingAttached3 + itemReceiver.GetCurrentGil() > item.GetItemData().maxStack) + { + return 3; + } + + return 0; } public InventoryItem CreateItem(uint itemId, int amount, byte quality = 1, InventoryItem.ItemModifier modifiers = null) diff --git a/FFXIVClassic Map Server/actors/chara/ItemPackage.cs b/FFXIVClassic Map Server/actors/chara/ItemPackage.cs index ed964671..1f9a3b18 100644 --- a/FFXIVClassic Map Server/actors/chara/ItemPackage.cs +++ b/FFXIVClassic Map Server/actors/chara/ItemPackage.cs @@ -32,12 +32,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.player public const ushort MAXSIZE_EQUIPMENT = 35; public const ushort MAXSIZE_EQUIPMENT_OTHERPLAYER = 0x23; - public enum INV_ERROR { - SUCCESS = 0, - INVENTORY_FULL, - ALREADY_HAS_UNIQUE, - SYSTEM_ERROR - }; + public const int ERROR_SUCCESS = 0; + public const int ERROR_FULL = 1; + public const int ERROR_HAS_UNIQUE = 2; + public const int ERROR_SYSTEM = 3; private Character owner; private ushort itemPackageCapacity; @@ -121,24 +119,64 @@ namespace FFXIVClassic_Map_Server.actors.chara.player return null; } - public INV_ERROR AddItem(uint itemId) + public int AddItem(uint itemId) { return AddItem(itemId, 1, 1); } - public INV_ERROR AddItem(uint itemId, int quantity) + public int AddItem(uint itemId, int quantity) { return AddItem(itemId, quantity, 1); } - public bool AddItems(uint[] itemIds) + public int AddItems(uint[] itemIds, uint[] quantity, byte[] quality) { - bool canAdd = GetFreeSlots() - itemIds.Length >= 0; - if (canAdd) + if (itemIds.Length != quantity.Length && itemIds.Length != quality.Length) + return ERROR_SYSTEM; + + //Check if has space + if (!CanAdd(itemIds, quantity, quality)) + return ERROR_FULL; + + for (int i = 0; i < itemIds.Length; i++) { - foreach (uint id in itemIds) + ItemData gItem = Server.GetItemGamedata(itemIds[i]); + + //If it's unique, abort + if (HasItem(itemIds[i]) && gItem.isExclusive) + return ERROR_HAS_UNIQUE; + + if (gItem == null) + { + Program.Log.Error("Inventory.AddItem: unable to find item %u", itemIds[i]); + return ERROR_SYSTEM; + } + + //Check if item id exists + int quantityCount = (int) quantity[i]; + for (int j = 0; j < endOfListIndex; j++) + { + InventoryItem item = list[j]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (item.itemId == itemIds[i] && item.quality == quantity[i] && item.quantity < gItem.maxStack) + { + int oldQuantity = item.quantity; + item.quantity = Math.Min(item.quantity + quantityCount, gItem.maxStack); + isDirty[j] = true; + quantityCount -= (gItem.maxStack - oldQuantity); + + DoDatabaseQuantity(item.uniqueId, item.quantity); + + if (quantityCount <= 0) + break; + } + } + + //New item that spilled over + while (quantityCount > 0) { - ItemData gItem = Server.GetItemGamedata(id); InventoryItem.ItemModifier modifiers = null; if (gItem.durability != 0) { @@ -146,31 +184,82 @@ namespace FFXIVClassic_Map_Server.actors.chara.player modifiers.durability = (uint)gItem.durability; } - InventoryItem addedItem = Database.CreateItem(id, Math.Min(1, gItem.maxStack), 0, modifiers); + InventoryItem addedItem = Database.CreateItem(itemIds[i], Math.Min(quantityCount, gItem.maxStack), quality[i], modifiers); addedItem.RefreshPositioning(owner, itemPackageCode, (ushort)endOfListIndex); isDirty[endOfListIndex] = true; list[endOfListIndex++] = addedItem; + quantityCount -= gItem.maxStack; + DoDatabaseAdd(addedItem); - } + } } - return canAdd; + + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } + + return ERROR_SUCCESS; } - public INV_ERROR AddItem(InventoryItem itemRef) + public bool CanAdd(uint[] itemIds, uint[] quantity, byte[] quality) + { + if (itemIds.Length != quantity.Length && itemIds.Length != quality.Length) + return false; + + int tempInvSize = GetCount(); + + for (int i = 0; i < itemIds.Length; i++) + { + ItemData gItem = Server.GetItemGamedata(itemIds[i]); + //Check if item id exists and fill up til maxstack + int quantityCount = (int) quantity[i]; + for (int j = 0; j < endOfListIndex; j++) + { + InventoryItem item = list[j]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (item.itemId == itemIds[i] && item.quality == quality[i] && item.quantity < gItem.maxStack) + { + quantityCount -= (gItem.maxStack - item.quantity); + if (quantityCount <= 0) + break; + } + } + + //New items that spilled over creating new stacks + while (quantityCount > 0) + { + quantityCount -= gItem.maxStack; + tempInvSize++; + } + + //If the new stacks push us over capacity, can't add these items + if (tempInvSize > itemPackageCapacity) + return false; + } + + return true; + } + + public int AddItem(InventoryItem itemRef) { //If it isn't a single item (ie: armor) just add like normal (not valid for BAZAAR) if (itemPackageCode != BAZAAR && itemRef.GetItemData().maxStack > 1) return AddItem(itemRef.itemId, itemRef.quantity, itemRef.quality); if (!IsSpaceForAdd(itemRef.itemId, itemRef.quantity, itemRef.quality)) - return INV_ERROR.INVENTORY_FULL; + return ERROR_FULL; ItemData gItem = Server.GetItemGamedata(itemRef.itemId); if (gItem == null) { Program.Log.Error("Inventory.AddItem: unable to find item %u", itemRef.itemId); - return INV_ERROR.SYSTEM_ERROR; + return ERROR_SYSTEM; } itemRef.RefreshPositioning(owner, itemPackageCode, (ushort)endOfListIndex); @@ -179,26 +268,31 @@ namespace FFXIVClassic_Map_Server.actors.chara.player list[endOfListIndex++] = itemRef; DoDatabaseAdd(itemRef); - SendUpdate(); + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } - return INV_ERROR.SUCCESS; + return ERROR_SUCCESS; } - public INV_ERROR AddItem(uint itemId, int quantity, byte quality) + public int AddItem(uint itemId, int quantity, byte quality) { if (!IsSpaceForAdd(itemId, quantity, quality)) - return INV_ERROR.INVENTORY_FULL; + return ERROR_FULL; ItemData gItem = Server.GetItemGamedata(itemId); //If it's unique, abort if (HasItem(itemId) && gItem.isExclusive) - return INV_ERROR.ALREADY_HAS_UNIQUE; + return ERROR_HAS_UNIQUE; if (gItem == null) { Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId); - return INV_ERROR.SYSTEM_ERROR; + return ERROR_SYSTEM; } //Check if item id exists @@ -242,15 +336,25 @@ namespace FFXIVClassic_Map_Server.actors.chara.player DoDatabaseAdd(addedItem); } - SendUpdate(); + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } - return INV_ERROR.SUCCESS; + return ERROR_SUCCESS; } public void SetItem(ushort slot, InventoryItem item) { list[slot] = item; - SendUpdate(); + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } item.RefreshPositioning(owner, itemPackageCode, slot); } @@ -309,7 +413,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player } DoRealign(); - SendUpdate(); + + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } } public void RemoveItem(InventoryItem item) @@ -358,7 +468,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player isDirty[slot] = true; DoRealign(); - SendUpdate(); + + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } } public void RemoveItemAtSlot(ushort slot) @@ -373,7 +489,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player isDirty[slot] = true; DoRealign(); - SendUpdate(); + + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } } public void RemoveItemAtSlot(ushort slot, int quantity) @@ -397,7 +519,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player DoDatabaseQuantity(list[slot].uniqueId, list[slot].quantity); isDirty[slot] = true; - SendUpdate(); + + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } } } @@ -411,7 +539,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.player } endOfListIndex = 0; - SendUpdate(); + if (owner is Player) + { + (owner as Player).QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + SendUpdate(); + (owner as Player).QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); + } } public void MarkDirty(InventoryItem item) diff --git a/FFXIVClassic Map Server/actors/chara/ReferencedItemPackage.cs b/FFXIVClassic Map Server/actors/chara/ReferencedItemPackage.cs index e17d80fa..0b8454bb 100644 --- a/FFXIVClassic Map Server/actors/chara/ReferencedItemPackage.cs +++ b/FFXIVClassic Map Server/actors/chara/ReferencedItemPackage.cs @@ -13,7 +13,7 @@ namespace FFXIVClassic_Map_Server.actors.chara const uint EMPTY = 0xFFFFFFFF; private readonly Player owner; - private readonly uint[] contentList; + private readonly InventoryItem[] referenceList; private readonly ushort itemPackageCode; private readonly ushort itemPackageCapacity; private bool writeToDB = false; @@ -23,13 +23,10 @@ namespace FFXIVClassic_Map_Server.actors.chara this.owner = owner; itemPackageCode = code; itemPackageCapacity = capacity; - contentList = new uint[capacity]; + referenceList = new InventoryItem[capacity]; if (code == ItemPackage.EQUIPMENT) writeToDB = true; - - for (int i = 0; i < contentList.Length; i++) - contentList[i] = EMPTY; } public void ToggleDBWrite(bool flag) @@ -38,25 +35,25 @@ namespace FFXIVClassic_Map_Server.actors.chara } #region Package Management - public void SetList(uint[] toSet) + public void SetList(InventoryItem[] toSet) { - Debug.Assert(contentList.Length == itemPackageCapacity); - toSet.CopyTo(contentList, 0); + Debug.Assert(referenceList.Length == itemPackageCapacity); + toSet.CopyTo(referenceList, 0); } - public void SetList(ushort[] positions, uint[] values) + public void SetList(ushort[] positions, InventoryItem[] values) { Debug.Assert(positions.Length == values.Length); for (int i = 0; i < positions.Length; i++) { - InventoryItem item = GetItem(values[i]); + InventoryItem item = values[i]; if (item == null) continue; //Database.EquipItem(owner, positions[i], item.uniqueId); - contentList[positions[i]] = values[i]; + referenceList[positions[i]] = values[i]; } owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); @@ -76,70 +73,70 @@ namespace FFXIVClassic_Map_Server.actors.chara public void Set(ushort position, InventoryItem item) { - if (position >= contentList.Length) + if (position >= referenceList.Length) return; if (writeToDB) Database.EquipItem(owner, position, item.uniqueId); ItemPackage newPackage = owner.GetItemPackage(item.itemPackage); - ItemPackage oldPackage = GetItemPackage(contentList[position]); - InventoryItem oldItem = GetItem(contentList[position]); + ItemPackage oldPackage = null; - if (oldPackage != null && oldItem != null) + if (referenceList[position] != null) + { + oldPackage = owner.GetItemPackage(referenceList[position].itemPackage); + InventoryItem oldItem = referenceList[position]; oldPackage.MarkDirty(oldItem); + } + newPackage.MarkDirty(item); - contentList[position] = GetValue(item.itemPackage, item.slot); + referenceList[position] = item; owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); if (oldPackage != null) oldPackage.SendUpdate(); newPackage.SendUpdate(); SendSingleUpdate(position); - owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); - - owner.CalculateBaseStats();// RecalculateStats(); + owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); } public void Clear(ushort position) { - if (position >= contentList.Length) + if (position >= referenceList.Length) return; if (writeToDB) Database.UnequipItem(owner, position); - ItemPackage oldItemPackage = GetItemPackage(contentList[position]); + ItemPackage oldItemPackage = owner.GetItemPackage(referenceList[position].itemPackage); - oldItemPackage.MarkDirty(GetItem(contentList[position])); - contentList[position] = EMPTY; + oldItemPackage.MarkDirty(referenceList[position]); + referenceList[position] = null; owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); oldItemPackage.SendUpdate(); SendSingleUpdate(position); owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); - - owner.RecalculateStats(); } public void ClearAll() { List packagesToRefresh = new List(); - for (int i = 0; i < contentList.Length; i++) + for (int i = 0; i < referenceList.Length; i++) { - if (contentList[i] == EMPTY) + if (referenceList[i] == null) continue; if (writeToDB) Database.UnequipItem(owner, (ushort)i); - ItemPackage package = GetItemPackage(contentList[i]); - package.MarkDirty(GetItem(contentList[i])); + ItemPackage package = owner.GetItemPackage(referenceList[i].itemPackage); + package.MarkDirty(referenceList[i]); packagesToRefresh.Add(package); - contentList[i] = EMPTY; + referenceList[i] = null; } owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); @@ -147,8 +144,6 @@ namespace FFXIVClassic_Map_Server.actors.chara packagesToRefresh[i].SendUpdate(); SendUpdate(); owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); - - owner.RecalculateStats(); } #endregion @@ -169,9 +164,9 @@ namespace FFXIVClassic_Map_Server.actors.chara { List slotsToUpdate = new List(); - for (ushort i = 0; i < contentList.Length; i++) + for (ushort i = 0; i < referenceList.Length; i++) { - if (contentList[i] != EMPTY) + if (referenceList[i] != null) slotsToUpdate.Add(i); } @@ -189,14 +184,14 @@ namespace FFXIVClassic_Map_Server.actors.chara { List items = new List(); - for (ushort i = 0; i < contentList.Length; i++) + for (ushort i = 0; i < referenceList.Length; i++) { - if (contentList[i] == EMPTY) + if (referenceList[i] == null) continue; - InventoryItem item = GetItem(contentList[i]); + InventoryItem item = referenceList[i]; item.linkSlot = i; //We have to set the linkSlot as this is the position in the Referenced IP, not the original IP it's linked from. - items.Add(GetItem(contentList[i])); + items.Add(referenceList[i]); } targetPlayer.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, destinationCapacity, destinationCode)); @@ -204,11 +199,11 @@ namespace FFXIVClassic_Map_Server.actors.chara targetPlayer.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); //Clean Up linkSlots - for (ushort i = 0; i < contentList.Length; i++) + for (ushort i = 0; i < referenceList.Length; i++) { - if (contentList[i] == EMPTY) + if (referenceList[i] == null) continue; - InventoryItem item = GetItem(contentList[i]); + InventoryItem item = referenceList[i]; item.linkSlot = 0xFFFF; } } @@ -217,10 +212,10 @@ namespace FFXIVClassic_Map_Server.actors.chara #region Packet Functions (Private) private void SendSingleLinkedItemPacket(Player targetPlayer, ushort position) { - if (contentList[position] == EMPTY) + if (referenceList[position] == null) targetPlayer.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, position)); else - targetPlayer.QueuePacket(LinkedItemListX01Packet.BuildPacket(owner.actorId, position, contentList[position])); + targetPlayer.QueuePacket(LinkedItemListX01Packet.BuildPacket(owner.actorId, position, referenceList[position])); } private void SendLinkedItemPackets(Player targetPlayer, List slotsToUpdate) @@ -230,16 +225,16 @@ namespace FFXIVClassic_Map_Server.actors.chara while (true) { if (slotsToUpdate.Count - currentIndex >= 64) - targetPlayer.QueuePacket(LinkedItemListX64Packet.BuildPacket(owner.actorId, contentList, slotsToUpdate, ref currentIndex)); + targetPlayer.QueuePacket(LinkedItemListX64Packet.BuildPacket(owner.actorId, referenceList, slotsToUpdate, ref currentIndex)); else if (slotsToUpdate.Count - currentIndex >= 32) - targetPlayer.QueuePacket(LinkedItemListX32Packet.BuildPacket(owner.actorId, contentList, slotsToUpdate, ref currentIndex)); + targetPlayer.QueuePacket(LinkedItemListX32Packet.BuildPacket(owner.actorId, referenceList, slotsToUpdate, ref currentIndex)); else if (slotsToUpdate.Count - currentIndex >= 16) - targetPlayer.QueuePacket(LinkedItemListX16Packet.BuildPacket(owner.actorId, contentList, slotsToUpdate, ref currentIndex)); + targetPlayer.QueuePacket(LinkedItemListX16Packet.BuildPacket(owner.actorId, referenceList, slotsToUpdate, ref currentIndex)); else if (slotsToUpdate.Count - currentIndex > 1) - targetPlayer.QueuePacket(LinkedItemListX08Packet.BuildPacket(owner.actorId, contentList, slotsToUpdate, ref currentIndex)); + targetPlayer.QueuePacket(LinkedItemListX08Packet.BuildPacket(owner.actorId, referenceList, slotsToUpdate, ref currentIndex)); else if (slotsToUpdate.Count - currentIndex == 1) { - targetPlayer.QueuePacket(LinkedItemListX01Packet.BuildPacket(owner.actorId, slotsToUpdate[currentIndex], contentList[slotsToUpdate[currentIndex]])); + targetPlayer.QueuePacket(LinkedItemListX01Packet.BuildPacket(owner.actorId, slotsToUpdate[currentIndex], referenceList[slotsToUpdate[currentIndex]])); currentIndex++; } else @@ -290,35 +285,11 @@ namespace FFXIVClassic_Map_Server.actors.chara public InventoryItem GetItemAtSlot(ushort position) { - if (position < contentList.Length) - return GetItem(contentList[position]); + if (position < referenceList.Length) + return referenceList[position]; else return null; } - #endregion - - #region Utils - private ItemPackage GetItemPackage(uint value) - { - if (value == EMPTY) - return null; - return owner.GetItemPackage((ushort)((value >> 16) & 0xFFFF)); - } - - private InventoryItem GetItem(uint value) - { - if (value == EMPTY) - return null; - ItemPackage package = GetItemPackage(value); - if (package != null) - return package.GetItemAtSlot((ushort)(value & 0xFFFF)); - return null; - } - - private uint GetValue(ushort code, ushort slot) - { - return (uint) ((code << 16) | slot); - } - #endregion + #endregion } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 8c213784..eaa2f2c7 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -982,7 +982,7 @@ namespace FFXIVClassic_Map_Server.Actors return max; } - public uint[] GetGearset(ushort classId) + public InventoryItem[] GetGearset(ushort classId) { return Database.GetEquipment(this, classId); } diff --git a/FFXIVClassic Map Server/dataobjects/InventoryItem.cs b/FFXIVClassic Map Server/dataobjects/InventoryItem.cs index be2c153a..c6c87382 100644 --- a/FFXIVClassic Map Server/dataobjects/InventoryItem.cs +++ b/FFXIVClassic Map Server/dataobjects/InventoryItem.cs @@ -24,8 +24,8 @@ namespace FFXIVClassic_Map_Server.dataobjects public uint itemId; public int quantity = 1; - public byte dealingVal = 0; - public byte dealingMode = DEALINGMODE_NONE; + public byte dealingVal = 0; + public byte dealingMode = DEALINGMODE_NONE; public int dealingAttached1 = 0; public int dealingAttached2 = 0; public int dealingAttached3 = 0; @@ -133,21 +133,7 @@ namespace FFXIVClassic_Map_Server.dataobjects tags[1] = itemData.isExclusive ? TAG_EXCLUSIVE : (byte)0; } - - //For check and trade commands - public InventoryItem(InventoryItem item, ushort slot) - { - this.uniqueId = item.uniqueId; - this.itemData = item.itemData; - this.itemId = item.itemId; - this.quantity = item.quantity; - this.slot = slot; - this.tags = item.tags; - this.tagValues = item.tagValues; - this.quality = item.quality; - this.modifiers = item.modifiers; - } - + public InventoryItem(uint uniqueId, ItemData itemData, int quantity, byte qualityNumber, ItemModifier modifiers = null) { this.uniqueId = uniqueId; @@ -318,6 +304,11 @@ namespace FFXIVClassic_Map_Server.dataobjects owner.GetItemPackage(itemPackage).MarkDirty(this); } + public int GetTradeQuantity() + { + return dealingAttached3; + } + public ItemData GetItemData() { return itemData; @@ -334,5 +325,6 @@ namespace FFXIVClassic_Map_Server.dataobjects { return GetBazaarMode() == TYPE_SINGLE || GetBazaarMode() == TYPE_MULTI || GetBazaarMode() == TYPE_STACK; } + } } diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX01Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX01Packet.cs index 59a5c9d2..fe427925 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX01Packet.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX01Packet.cs @@ -2,6 +2,7 @@ using System.IO; using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.dataobjects; namespace FFXIVClassic_Map_Server.packets.send.actor.inventory { @@ -10,7 +11,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory public const ushort OPCODE = 0x014D; public const uint PACKET_SIZE = 0x28; - public static SubPacket BuildPacket(uint playerActorID, ushort position, uint linkedItem) + public static SubPacket BuildPacket(uint playerActorID, ushort position, InventoryItem linkedItem) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -19,28 +20,12 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory using (BinaryWriter binWriter = new BinaryWriter(mem)) { binWriter.Write((UInt16)position); - binWriter.Write((UInt32)linkedItem); + binWriter.Write((UInt16)linkedItem.slot); + binWriter.Write((UInt16)linkedItem.itemPackage); } } return new SubPacket(OPCODE, playerActorID, data); - } - - public static SubPacket BuildPacket(uint playerActorID, ushort position, ushort itemSlot, ushort itemPackageCode) - { - byte[] data = new byte[PACKET_SIZE - 0x20]; - - using (MemoryStream mem = new MemoryStream(data)) - { - using (BinaryWriter binWriter = new BinaryWriter(mem)) - { - binWriter.Write((UInt16)position); - binWriter.Write((UInt16)itemSlot); - binWriter.Write((UInt16)itemPackageCode); - } - } - - return new SubPacket(OPCODE, playerActorID, data); - } + } } } diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX08Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX08Packet.cs index 41f344f0..220dc8bb 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX08Packet.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX08Packet.cs @@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory public const ushort OPCODE = 0x14E; public const uint PACKET_SIZE = 0x58; - public static SubPacket BuildPacket(uint playerActorId, uint[] linkedItemList, List slotsToUpdate, ref int listOffset) + public static SubPacket BuildPacket(uint playerActorId, InventoryItem[] linkedItemList, List slotsToUpdate, ref int listOffset) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -29,7 +29,8 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory for (int i = 0; i < max; i++) { binWriter.Write((UInt16)slotsToUpdate[i]); //LinkedItemPackageSlot - binWriter.Write((UInt32)linkedItemList[slotsToUpdate[i]]); //ItemPackage Slot + ItemPackage Code + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].slot); //ItemPackage Slot + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].itemPackage); //ItemPackage Code listOffset++; } diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX16Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX16Packet.cs index 77375726..6eda3cff 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX16Packet.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX16Packet.cs @@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory public const ushort OPCODE = 0x14F; public const uint PACKET_SIZE = 0x80; - public static SubPacket BuildPacket(uint playerActorId, uint[] linkedItemList, List slotsToUpdate, ref int listOffset) + public static SubPacket BuildPacket(uint playerActorId, InventoryItem[] linkedItemList, List slotsToUpdate, ref int listOffset) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -29,7 +29,8 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory for (int i = 0; i < max; i++) { binWriter.Write((UInt16)slotsToUpdate[i]); //LinkedItemPackageSlot - binWriter.Write((UInt32)linkedItemList[slotsToUpdate[i]]); //ItemPackage Slot + ItemPackage Code + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].slot); //ItemPackage Slot + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].itemPackage); //ItemPackage Code listOffset++; } diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX32Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX32Packet.cs index 417a085f..8fd2c519 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX32Packet.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX32Packet.cs @@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory public const ushort OPCODE = 0x150; public const uint PACKET_SIZE = 0xE0; - public static SubPacket BuildPacket(uint playerActorId, uint[] linkedItemList, List slotsToUpdate, ref int listOffset) + public static SubPacket BuildPacket(uint playerActorId, InventoryItem[] linkedItemList, List slotsToUpdate, ref int listOffset) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -29,7 +29,8 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory for (int i = 0; i < max; i++) { binWriter.Write((UInt16)slotsToUpdate[i]); //LinkedItemPackageSlot - binWriter.Write((UInt32)linkedItemList[slotsToUpdate[i]]); //ItemPackage Slot + ItemPackage Code + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].slot); //ItemPackage Slot + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].itemPackage); //ItemPackage Code listOffset++; } diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX64Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX64Packet.cs index edc7378a..c9886704 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX64Packet.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/LinkedItemListX64Packet.cs @@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory public const ushort OPCODE = 0x151; public const uint PACKET_SIZE = 0x194; - public static SubPacket BuildPacket(uint playerActorId, uint[] linkedItemList, List slotsToUpdate, ref int listOffset) + public static SubPacket BuildPacket(uint playerActorId, InventoryItem[] linkedItemList, List slotsToUpdate, ref int listOffset) { byte[] data = new byte[PACKET_SIZE - 0x20]; @@ -29,7 +29,8 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.inventory for (int i = 0; i < max; i++) { binWriter.Write((UInt16)slotsToUpdate[i]); //LinkedItemPackageSlot - binWriter.Write((UInt32)linkedItemList[slotsToUpdate[i]]); //ItemPackage Slot + ItemPackage Code + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].slot); //ItemPackage Slot + binWriter.Write((UInt16)linkedItemList[slotsToUpdate[i]].itemPackage); //ItemPackage Code listOffset++; } diff --git a/data/scripts/commands/EquipCommand.lua b/data/scripts/commands/EquipCommand.lua index 6c66c03a..576a5f8b 100644 --- a/data/scripts/commands/EquipCommand.lua +++ b/data/scripts/commands/EquipCommand.lua @@ -69,6 +69,8 @@ function onEventStarted(player, actor, triggerName, equippedItem, param1, param2 end end + player.CalculateBaseStats(); --player.RecalculateStats(); + player:EndEvent(); end diff --git a/data/scripts/commands/TradeExecuteCommand.lua b/data/scripts/commands/TradeExecuteCommand.lua index 7dc75c04..590a0458 100644 --- a/data/scripts/commands/TradeExecuteCommand.lua +++ b/data/scripts/commands/TradeExecuteCommand.lua @@ -55,7 +55,7 @@ function onEventStarted(player, actor, triggerName) --Check if both accepted the trade if (player:IsTradeAccepted() and player:GetOtherTrader():IsTradeAccepted()) then callClientFunction(player, "delegateCommand", GetStaticActor("TradeExecuteCommand"), "processTradeCommandCloseTray"); - GetWorldManager():SwapTradedItems(player, player:GetOtherTrader()); + GetWorldManager():CompleteTrade(player, player:GetOtherTrader()); break; end