diff --git a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs index 7daff426..35c86cf0 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs @@ -7,71 +7,71 @@ using FFXIVClassic_Map_Server.packets.send.actor.inventory; using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; - -namespace FFXIVClassic_Map_Server.actors.chara.player -{ - class Inventory - { +using System.Linq; + +namespace FFXIVClassic_Map_Server.actors.chara.player +{ + class Inventory + { public const ushort NORMAL = 0; //Max 0xC8 - public const ushort UNKNOWN = 1; //Max 0x96 - public const ushort LOOT = 4; //Max 0xA + public const ushort UNKNOWN = 1; //Max 0x96 + public const ushort LOOT = 4; //Max 0xA public const ushort MELDREQUEST = 5; //Max 0x04 - public const ushort BAZAAR = 7; //Max 0x0A - public const ushort CURRENCY_CRYSTALS = 99; //Max 0x140 - public const ushort KEYITEMS = 100; //Max 0x500 + public const ushort BAZAAR = 7; //Max 0x0A + public const ushort CURRENCY_CRYSTALS = 99; //Max 0x140 + public const ushort KEYITEMS = 100; //Max 0x500 public const ushort EQUIPMENT = 0x00FE; //Max 0x23 - public const ushort TRADE = 0x00FD; //Max 0x04 + public const ushort TRADE = 0x00FD; //Max 0x04 public const ushort EQUIPMENT_OTHERPLAYER = 0x00F9; //Max 0x23 - - public enum INV_ERROR { - SUCCESS = 0, + + public enum INV_ERROR { + SUCCESS = 0, INVENTORY_FULL, ALREADY_HAS_UNIQUE, SYSTEM_ERROR - }; - - private Character owner; - private ushort itemPackageCapacity; + }; + + private Character owner; + private ushort itemPackageCapacity; private ushort itemPackageCode; - private bool isTemporary; + private bool isTemporary; private InventoryItem[] list; private bool[] isDirty; private bool holdingUpdates = false; private int endOfListIndex = 0; - public Inventory(Character ownerPlayer, ushort capacity, ushort code, bool temporary = false) - { - owner = ownerPlayer; - itemPackageCapacity = capacity; + public Inventory(Character ownerPlayer, ushort capacity, ushort code, bool temporary = false) + { + owner = ownerPlayer; + itemPackageCapacity = capacity; itemPackageCode = code; isTemporary = temporary; list = new InventoryItem[capacity]; - isDirty = new bool[capacity]; - } - - #region Inventory Management - public void InitList(List itemsFromDB) - { + isDirty = new bool[capacity]; + } + + #region Inventory Management + public void InitList(List itemsFromDB) + { int i = 0; foreach (InventoryItem item in itemsFromDB) { - item.RefreshPositioning(itemPackageCode, (ushort) i); + item.RefreshPositioning(owner, itemPackageCode, (ushort) i); list[i++] = item; } - endOfListIndex = i; - } - - public InventoryItem GetItemAtSlot(ushort slot) - { - if (slot < list.Length) - return list[slot]; - else - return null; - } - - public InventoryItem GetItemByUniqueId(ulong uniqueItemId) + endOfListIndex = i; + } + + public InventoryItem GetItemAtSlot(ushort slot) + { + if (slot < list.Length) + return list[slot]; + else + return null; + } + + public InventoryItem GetItemByUniqueId(ulong uniqueItemId) { for (int i = 0; i < endOfListIndex; i++) { @@ -79,10 +79,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.player Debug.Assert(item != null, "Item slot was null!!!"); - if (item.uniqueId == uniqueItemId) - return item; - } - return null; + if (item.uniqueId == uniqueItemId) + return item; + } + return null; } public InventoryItem GetItemByCatelogId(ulong catelogId) @@ -99,171 +99,197 @@ namespace FFXIVClassic_Map_Server.actors.chara.player return null; } + public InventoryItem GetItemAttachedTo(InventoryItem attachedTo) + { + for (int i = 0; i < endOfListIndex; i++) + { + InventoryItem item = list[i]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (attachedTo.GetAttached() == item.uniqueId) + return item; + } + return null; + } + public INV_ERROR AddItem(uint itemId) { return AddItem(itemId, 1, 1); } - public INV_ERROR AddItem(uint itemId, int quantity) + public INV_ERROR AddItem(uint itemId, int quantity) { - return AddItem(itemId, quantity, 1); + return AddItem(itemId, quantity, 1); } public INV_ERROR 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; - - ItemData gItem = Server.GetItemGamedata(itemRef.itemId); - - if (gItem == null) + { + lock (inventoryLock) { - Program.Log.Error("Inventory.AddItem: unable to find item %u", itemRef.itemId); - return INV_ERROR.SYSTEM_ERROR; - } + //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); - itemRef.RefreshPositioning(itemPackageCode, (ushort) endOfListIndex); + if (!IsSpaceForAdd(itemRef.itemId, itemRef.quantity, itemRef.quality)) + return INV_ERROR.INVENTORY_FULL; - isDirty[endOfListIndex] = true; - list[endOfListIndex++] = itemRef; - DoDatabaseAdd(itemRef); + ItemData gItem = Server.GetItemGamedata(itemRef.itemId); - SendUpdatePackets(); - - return INV_ERROR.SUCCESS; - } - - public INV_ERROR AddItem(uint itemId, int quantity, byte quality) - { - if (!IsSpaceForAdd(itemId, quantity, quality)) - return INV_ERROR.INVENTORY_FULL; - - ItemData gItem = Server.GetItemGamedata(itemId); - - //If it's unique, abort - if (HasItem(itemId) && gItem.isExclusive) - return INV_ERROR.ALREADY_HAS_UNIQUE; - - if (gItem == null) - { - Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId); - return INV_ERROR.SYSTEM_ERROR; - } - - //Check if item id exists - int quantityCount = quantity; - for (int i = 0; i < endOfListIndex; i++) - { - InventoryItem item = list[i]; - - Debug.Assert(item != null, "Item slot was null!!!"); - - if (item.itemId == itemId && item.quality == quality && item.quantity < gItem.maxStack) - { - int oldQuantity = item.quantity; - item.quantity = Math.Min(item.quantity + quantityCount, gItem.maxStack); - isDirty[i] = true; - quantityCount -= (gItem.maxStack - oldQuantity); - - DoDatabaseQuantity(item.uniqueId, item.quantity); - - if (quantityCount <= 0) - break; - } - } - - //New item that spilled over - while (quantityCount > 0) - { - InventoryItem.ItemModifier modifiers = null; - if (gItem.durability != 0) + if (gItem == null) { - modifiers = new InventoryItem.ItemModifier(); - modifiers.durability = (uint)gItem.durability; - } - - InventoryItem addedItem = Database.CreateItem(itemId, Math.Min(quantityCount, gItem.maxStack), quality, modifiers); - addedItem.RefreshPositioning(itemPackageCode, (ushort)endOfListIndex); + Program.Log.Error("Inventory.AddItem: unable to find item %u", itemRef.itemId); + return INV_ERROR.SYSTEM_ERROR; + } + + itemRef.RefreshPositioning(owner, itemPackageCode, (ushort)endOfListIndex); + isDirty[endOfListIndex] = true; - list[endOfListIndex++] = addedItem; - quantityCount -= gItem.maxStack; + list[endOfListIndex++] = itemRef; + DoDatabaseAdd(itemRef); - DoDatabaseAdd(addedItem); + SendUpdatePackets(); + + return INV_ERROR.SUCCESS; } + } - SendUpdatePackets(); - - return INV_ERROR.SUCCESS; + public INV_ERROR AddItem(uint itemId, int quantity, byte quality) + { + lock (inventoryLock) + { + if (!IsSpaceForAdd(itemId, quantity, quality)) + return INV_ERROR.INVENTORY_FULL; + + ItemData gItem = Server.GetItemGamedata(itemId); + + //If it's unique, abort + if (HasItem(itemId) && gItem.isExclusive) + return INV_ERROR.ALREADY_HAS_UNIQUE; + + if (gItem == null) + { + Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId); + return INV_ERROR.SYSTEM_ERROR; + } + + //Check if item id exists + int quantityCount = quantity; + for (int i = 0; i < endOfListIndex; i++) + { + InventoryItem item = list[i]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (item.itemId == itemId && item.quality == quality && item.quantity < gItem.maxStack) + { + int oldQuantity = item.quantity; + item.quantity = Math.Min(item.quantity + quantityCount, gItem.maxStack); + isDirty[i] = true; + quantityCount -= (gItem.maxStack - oldQuantity); + + DoDatabaseQuantity(item.uniqueId, item.quantity); + + if (quantityCount <= 0) + break; + } + } + + //New item that spilled over + while (quantityCount > 0) + { + InventoryItem.ItemModifier modifiers = null; + if (gItem.durability != 0) + { + modifiers = new InventoryItem.ItemModifier(); + modifiers.durability = (uint)gItem.durability; + } + + InventoryItem addedItem = Database.CreateItem(itemId, Math.Min(quantityCount, gItem.maxStack), quality, modifiers); + addedItem.RefreshPositioning(owner, itemPackageCode, (ushort)endOfListIndex); + isDirty[endOfListIndex] = true; + list[endOfListIndex++] = addedItem; + quantityCount -= gItem.maxStack; + + DoDatabaseAdd(addedItem); + } + + SendUpdatePackets(); + + return INV_ERROR.SUCCESS; + } } public void SetItem(ushort slot, InventoryItem item) { - list[slot] = item; - SendUpdatePackets(); - item.RefreshPositioning(itemPackageCode, slot); - } - + lock (inventoryLock) + { + list[slot] = item; + SendUpdatePackets(); + item.RefreshPositioning(owner, itemPackageCode, slot); + } + } + public void RemoveItem(uint itemId) { RemoveItem(itemId, 1); - } - + } + public void RemoveItem(uint itemId, int quantity) { RemoveItem(itemId, quantity, 1); - } - - public void RemoveItem(uint itemId, int quantity, int quality) - { - if (!HasItem(itemId, quantity, quality)) - return; - - List slotsToUpdate = new List(); - List itemsToRemove = new List(); - List slotsToRemove = new List(); - List AddItemPackets = new List(); - - //Remove as we go along - int quantityCount = quantity; - ushort lowestSlot = 0; - for (int i = endOfListIndex - 1; i >= 0; i--) - { - InventoryItem item = list[i]; + } - Debug.Assert(item != null, "Item slot was null!!!"); - - if (item.itemId == itemId && item.quality == quality) - { - int oldQuantity = item.quantity; - //Stack nomnomed - if (item.quantity - quantityCount <= 0) + public void RemoveItem(uint itemId, int quantity, int quality) + { + lock (inventoryLock) + { + if (!HasItem(itemId, quantity, quality)) + return; + + List slotsToUpdate = new List(); + List itemsToRemove = new List(); + List slotsToRemove = new List(); + List AddItemPackets = new List(); + + //Remove as we go along + int quantityCount = quantity; + ushort lowestSlot = 0; + for (int i = endOfListIndex - 1; i >= 0; i--) + { + InventoryItem item = list[i]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (item.itemId == itemId && item.quality == quality) { - DoDatabaseRemove(list[i].uniqueId); - list[i] = null; + int oldQuantity = item.quantity; + //Stack nomnomed + if (item.quantity - quantityCount <= 0) + { + DoDatabaseRemove(list[i].uniqueId); + list[i] = null; + } + //Stack reduced + else + { + item.quantity -= quantityCount; + DoDatabaseQuantity(list[i].uniqueId, list[i].quantity); + } + + isDirty[i] = true; + + quantityCount -= oldQuantity; + lowestSlot = item.slot; + + if (quantityCount <= 0) + break; } - //Stack reduced - else - { - item.quantity -= quantityCount; - DoDatabaseQuantity(list[i].uniqueId, list[i].quantity); - } + } - isDirty[i] = true; - - quantityCount -= oldQuantity; - lowestSlot = item.slot; - - if (quantityCount <= 0) - break; - } + DoRealign(); + SendUpdatePackets(); } - - DoRealign(); - SendUpdatePackets(); } public void RemoveItem(InventoryItem item) @@ -276,237 +302,273 @@ namespace FFXIVClassic_Map_Server.actors.chara.player RemoveItemByUniqueId(item.uniqueId, quantity); } - public void RemoveItemByUniqueId(ulong itemDBId, int quantity) - { - ushort slot = 0; - InventoryItem toDelete = null; - for (int i = 0; i < endOfListIndex; i++) + public void RemoveItemByUniqueId(ulong itemDBId, int quantity) + { + lock (inventoryLock) { - InventoryItem item = list[i]; - - Debug.Assert(item != null, "Item slot was null!!!"); - - if (item.uniqueId == itemDBId) + ushort slot = 0; + InventoryItem toDelete = null; + for (int i = 0; i < endOfListIndex; i++) { - toDelete = item; - break; + InventoryItem item = list[i]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (item.uniqueId == itemDBId) + { + toDelete = item; + break; + } + slot++; } - slot++; - } - - if (toDelete == null) - return; - if (quantity >= toDelete.quantity) - { - DoDatabaseRemove(toDelete.uniqueId); - list[slot].RefreshPositioning(0xFFFF, 0xFFFF); - list[slot] = null; + if (toDelete == null) + return; + + if (quantity >= toDelete.quantity) + { + DoDatabaseRemove(toDelete.uniqueId); + list[slot].RefreshPositioning(null, 0xFFFF, 0xFFFF); + list[slot] = null; + } + else + { + list[slot].quantity -= quantity; + DoDatabaseQuantity(list[slot].uniqueId, list[slot].quantity); + } + + isDirty[slot] = true; + + DoRealign(); + SendUpdatePackets(); } - else + } + + public void RemoveItemAtSlot(ushort slot) + { + lock (inventoryLock) { - list[slot].quantity -= quantity; - DoDatabaseQuantity(list[slot].uniqueId, list[slot].quantity); - } - - isDirty[slot] = true; + if (slot >= endOfListIndex) + return; - DoRealign(); - SendUpdatePackets(); - } - - public void RemoveItemAtSlot(ushort slot) - { - if (slot >= endOfListIndex) - return; + DoDatabaseRemove(list[slot].uniqueId); - DoDatabaseRemove(list[slot].uniqueId); + list[slot].RefreshPositioning(null, 0xFFFF, 0xFFFF); + list[slot] = null; + isDirty[slot] = true; - list[slot].RefreshPositioning(0xFFFF, 0xFFFF); - list[slot] = null; - isDirty[slot] = true; - - DoRealign(); - SendUpdatePackets(); + DoRealign(); + SendUpdatePackets(); + } } public void RemoveItemAtSlot(ushort slot, int quantity) { - if (slot >= endOfListIndex) - return; - - if (list[slot] != null) + lock (inventoryLock) { - list[slot].quantity -= quantity; + if (slot >= endOfListIndex) + return; - if (list[slot].quantity <= 0) + if (list[slot] != null) { - DoDatabaseRemove(list[slot].uniqueId); + list[slot].quantity -= quantity; - list[slot].RefreshPositioning(0xFFFF, 0xFFFF); - list[slot] = null; - DoRealign(); + if (list[slot].quantity <= 0) + { + DoDatabaseRemove(list[slot].uniqueId); + + list[slot].RefreshPositioning(null, 0xFFFF, 0xFFFF); + list[slot] = null; + DoRealign(); + } + else + DoDatabaseQuantity(list[slot].uniqueId, list[slot].quantity); + + isDirty[slot] = true; + SendUpdatePackets(); } - else - DoDatabaseQuantity(list[slot].uniqueId, list[slot].quantity); + } + } - isDirty[slot] = true; - SendUpdatePackets(); - } - } - public void Clear() { - for (int i = 0; i < endOfListIndex; i++) + lock (inventoryLock) { - list[i].RefreshPositioning(0xFFFF, 0xFFFF); - list[i] = null; - isDirty[i] = true; - } - endOfListIndex = 0; + for (int i = 0; i < endOfListIndex; i++) + { + list[i].RefreshPositioning(null, 0xFFFF, 0xFFFF); + list[i] = null; + isDirty[i] = true; + } + endOfListIndex = 0; + + SendUpdatePackets(); + } + } - SendUpdatePackets(); - } - public InventoryItem[] GetRawList() { return list; - } - - public void ChangeDurability(uint slot, uint durabilityChange) - { - isDirty[slot] = true; - } - - public void ChangeSpiritBind(uint slot, uint spiritBindChange) - { - isDirty[slot] = true; - } - - public void ChangeMateria(uint slot, byte materiaSlot, byte materiaId) - { - isDirty[slot] = true; - } - #endregion - - #region Packet Functions - public void SendFullInventory(Player player) - { - player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); - SendInventoryPackets(player, 0); - player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); } - private void SendInventoryPackets(Player player, InventoryItem item) + public void ChangeDurability(uint slot, uint durabilityChange) { - player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, item)); + isDirty[slot] = true; } - private void SendInventoryPackets(Player player, List items) - { - int currentIndex = 0; - - while (true) - { - if (items.Count - currentIndex >= 64) - player.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, items, ref currentIndex)); - else if (items.Count - currentIndex >= 32) - player.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, items, ref currentIndex)); - else if (items.Count - currentIndex >= 16) - player.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, items, ref currentIndex)); - else if (items.Count - currentIndex > 1) - player.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, items, ref currentIndex)); - else if (items.Count - currentIndex == 1) - { - player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, items[currentIndex])); - currentIndex++; - } - else - break; - } - + public void ChangeSpiritBind(uint slot, uint spiritBindChange) + { + isDirty[slot] = true; } - private void SendInventoryPackets(Player player, int startOffset) - { - int currentIndex = startOffset; + public void ChangeMateria(uint slot, byte materiaSlot, byte materiaId) + { + isDirty[slot] = true; + } + #endregion - List lst = new List(); - for (int i = 0; i < endOfListIndex; i++) - lst.Add(list[i]); - - while (true) + #region Packet Functions + public void SendFullInventory(Player player) + { + lock (inventoryLock) { - if (endOfListIndex - currentIndex >= 64) - player.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); - else if (endOfListIndex - currentIndex >= 32) - player.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); - else if (endOfListIndex - currentIndex >= 16) - player.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); - else if (endOfListIndex - currentIndex > 1) - player.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); - else if (endOfListIndex - currentIndex == 1) - { - player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, list[currentIndex])); - currentIndex++; - } - else - break; - } - + player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); + SendInventoryPackets(player, 0); + player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + } } - private void SendInventoryRemovePackets(Player player, ushort index) - { - player.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, index)); + private void SendInventoryPackets(Player player, InventoryItem item) + { + lock (inventoryLock) + { + player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, item)); + } } - - private void SendInventoryRemovePackets(Player player, List indexes) - { - int currentIndex = 0; - - while (true) - { - if (indexes.Count - currentIndex >= 64) - player.QueuePacket(InventoryRemoveX64Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); - else if (indexes.Count - currentIndex >= 32) - player.QueuePacket(InventoryRemoveX32Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); - else if (indexes.Count - currentIndex >= 16) - player.QueuePacket(InventoryRemoveX16Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); - else if (indexes.Count - currentIndex > 1) - player.QueuePacket(InventoryRemoveX08Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); - else if (indexes.Count - currentIndex == 1) + + private void SendInventoryPackets(Player player, List items) + { + lock (inventoryLock) + { + int currentIndex = 0; + + while (true) { - player.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, indexes[currentIndex])); - currentIndex++; - } - else - break; - } - + if (items.Count - currentIndex >= 64) + player.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, items, ref currentIndex)); + else if (items.Count - currentIndex >= 32) + player.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, items, ref currentIndex)); + else if (items.Count - currentIndex >= 16) + player.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, items, ref currentIndex)); + else if (items.Count - currentIndex > 1) + player.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, items, ref currentIndex)); + else if (items.Count - currentIndex == 1) + { + player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, items[currentIndex])); + currentIndex++; + } + else + break; + } + } + } + + private void SendInventoryPackets(Player player, int startOffset) + { + lock (inventoryLock) + { + int currentIndex = startOffset; + + List lst = new List(); + for (int i = 0; i < endOfListIndex; i++) + lst.Add(list[i]); + + while (true) + { + if (endOfListIndex - currentIndex >= 64) + player.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); + else if (endOfListIndex - currentIndex >= 32) + player.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); + else if (endOfListIndex - currentIndex >= 16) + player.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); + else if (endOfListIndex - currentIndex > 1) + player.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, lst, ref currentIndex)); + else if (endOfListIndex - currentIndex == 1) + { + player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, list[currentIndex])); + currentIndex++; + } + else + break; + } + } + } + + private void SendInventoryRemovePackets(Player player, ushort index) + { + lock (inventoryLock) + { + player.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, index)); + } + } + + private void SendInventoryRemovePackets(Player player, List indexes) + { + lock (inventoryLock) + { + int currentIndex = 0; + + while (true) + { + if (indexes.Count - currentIndex >= 64) + player.QueuePacket(InventoryRemoveX64Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); + else if (indexes.Count - currentIndex >= 32) + player.QueuePacket(InventoryRemoveX32Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); + else if (indexes.Count - currentIndex >= 16) + player.QueuePacket(InventoryRemoveX16Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); + else if (indexes.Count - currentIndex > 1) + player.QueuePacket(InventoryRemoveX08Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); + else if (indexes.Count - currentIndex == 1) + { + player.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, indexes[currentIndex])); + currentIndex++; + } + else + break; + } + } } public void RefreshItem(Player player, InventoryItem item) { - player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); - SendInventoryPackets(player, item); - player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + lock (inventoryLock) + { + player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); + SendInventoryPackets(player, item); + player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + } } public void RefreshItem(Player player, params InventoryItem[] items) { - player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); - SendInventoryPackets(player, items.ToList()); - player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + lock (inventoryLock) + { + player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); + SendInventoryPackets(player, items.ToList()); + player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + } } public void RefreshItem(Player player, List items) { - player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); - SendInventoryPackets(player, items); - player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); - } - + lock (inventoryLock) + { + player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); + SendInventoryPackets(player, items); + player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + } + } + #endregion #region Automatic Client and DB Updating @@ -533,11 +595,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.player if (itemPackageCode == BAZAAR) return; - - if (owner is Player) - Database.SetQuantity((Player)owner, itemDBId, itemPackageCode); - else if (owner is Retainer) - Database.SetQuantity((Retainer)owner, itemDBId, itemPackageCode); + + Database.SetQuantity(itemDBId, quantity); } private void DoDatabaseRemove(ulong itemDBId) @@ -564,34 +623,37 @@ namespace FFXIVClassic_Map_Server.actors.chara.player public void SendUpdatePackets(Player player) { - List items = new List(); - List slotsToRemove = new List(); - - for (int i = 0; i < list.Length; i++) + lock (inventoryLock) { - if (i == endOfListIndex) - break; - if (isDirty[i]) - items.Add(list[i]); + List items = new List(); + List slotsToRemove = new List(); + + for (int i = 0; i < list.Length; i++) + { + if (i == endOfListIndex) + break; + if (isDirty[i]) + items.Add(list[i]); + } + + for (int i = endOfListIndex; i < list.Length; i++) + { + if (isDirty[i]) + slotsToRemove.Add((ushort)i); + } + + if (!holdingUpdates) + Array.Clear(isDirty, 0, isDirty.Length); + + player.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); + player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); + //Send Updated Slots + SendInventoryPackets(player, items); + //Send Remove packets for tail end + SendInventoryRemovePackets(player, slotsToRemove); + player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); + player.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); } - - for (int i = endOfListIndex; i < list.Length; i++) - { - if (isDirty[i]) - slotsToRemove.Add((ushort)i); - } - - if (!holdingUpdates) - Array.Clear(isDirty, 0, isDirty.Length); - - player.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); - player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, itemPackageCapacity, itemPackageCode)); - //Send Updated Slots - SendInventoryPackets(player, items); - //Send Remove packets for tail end - SendInventoryRemovePackets(player, slotsToRemove); - player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); - player.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId)); } public void StartSendUpdate() @@ -610,64 +672,70 @@ namespace FFXIVClassic_Map_Server.actors.chara.player #region Inventory Utils - public bool IsFull() - { - return endOfListIndex >= itemPackageCapacity; - } - - public bool IsSpaceForAdd(uint itemId, int quantity, int quality) - { - int quantityCount = quantity; - for (int i = 0; i < endOfListIndex; i++) - { - InventoryItem item = list[i]; - ItemData gItem = Server.GetItemGamedata(item.itemId); - if (item.itemId == itemId && item.quality == quality && item.quantity < gItem.maxStack) - { - quantityCount -= (gItem.maxStack - item.quantity); - if (quantityCount <= 0) - break; - } - } - - return quantityCount <= 0 || (quantityCount > 0 && !IsFull()); - } - - public bool HasItem(uint itemId) - { - return HasItem(itemId, 1); + public bool IsFull() + { + return endOfListIndex >= itemPackageCapacity; + } + + public bool IsSpaceForAdd(uint itemId, int quantity, int quality) + { + lock (inventoryLock) + { + int quantityCount = quantity; + for (int i = 0; i < endOfListIndex; i++) + { + InventoryItem item = list[i]; + ItemData gItem = Server.GetItemGamedata(item.itemId); + if (item.itemId == itemId && item.quality == quality && item.quantity < gItem.maxStack) + { + quantityCount -= (gItem.maxStack - item.quantity); + if (quantityCount <= 0) + break; + } + } + + return quantityCount <= 0 || (quantityCount > 0 && !IsFull()); + } + } + + public bool HasItem(uint itemId) + { + return HasItem(itemId, 1); } public bool HasItem(uint itemId, int minQuantity) { return HasItem(itemId, minQuantity, 1); - } - - public bool HasItem(uint itemId, int minQuantity, int quality) - { - int count = 0; + } - for (int i = endOfListIndex - 1; i >= 0; i--) - { - InventoryItem item = list[i]; - - Debug.Assert(item != null, "Item slot was null!!!"); - - if (item.itemId == itemId && item.quality == quality) - count += item.quantity; - - if (count >= minQuantity) - return true; - } - - return false; - } - - public int GetNextEmptySlot() + public bool HasItem(uint itemId, int minQuantity, int quality) { - return endOfListIndex; - } - + lock (inventoryLock) + { + int count = 0; + + for (int i = endOfListIndex - 1; i >= 0; i--) + { + InventoryItem item = list[i]; + + Debug.Assert(item != null, "Item slot was null!!!"); + + if (item.itemId == itemId && item.quality == quality) + count += item.quantity; + + if (count >= minQuantity) + return true; + } + + return false; + } + } + + public int GetNextEmptySlot() + { + return endOfListIndex; + } + private void DoRealign() { int lastNullSlot = -1; @@ -692,8 +760,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.player if (lastNullSlot != -1) endOfListIndex = lastNullSlot; - } - + } + #endregion @@ -701,5 +769,5 @@ namespace FFXIVClassic_Map_Server.actors.chara.player { return endOfListIndex; } - } -} + } +} diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index d66db97d..f875e54f 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -1691,6 +1691,8 @@ namespace FFXIVClassic_Map_Server.Actors if (actor == null) return; + runningEvents.Pop(); + List lParams = LuaUtils.CreateLuaParamList(parameters); SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, 0x75dc1, conditionName, lParams); spacket.DebugPrintSubPacket(); @@ -1702,6 +1704,8 @@ namespace FFXIVClassic_Map_Server.Actors if (actor == null) return; + runningEvents.Pop(); + List lParams = LuaUtils.CreateLuaParamList(parameters); SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, unknown, conditionName, lParams); spacket.DebugPrintSubPacket();