Rewrote the inventory code, splitting the packet updates from the list updates.

This commit is contained in:
Filip Maj 2017-09-05 14:44:06 -04:00
parent f437b36f5a
commit 81d82cd7a8
5 changed files with 224 additions and 277 deletions

View File

@ -1265,7 +1265,7 @@ namespace FFXIVClassic_Map_Server
byte materia4 = reader.GetByte(11); byte materia4 = reader.GetByte(11);
byte materia5 = reader.GetByte(12); byte materia5 = reader.GetByte(12);
items.Add(new InventoryItem(uniqueId, itemId, quantity, slot, itemType, qualityNumber, durability, spiritBind, materia1, materia2, materia3, materia4, materia5)); items.Add(new InventoryItem(uniqueId, itemId, quantity, itemType, qualityNumber, durability, spiritBind, materia1, materia2, materia3, materia4, materia5));
} }
} }
} }
@ -1282,7 +1282,7 @@ namespace FFXIVClassic_Map_Server
return items; return items;
} }
public static InventoryItem AddItem(Player player, uint itemId, int quantity, byte quality, byte itemType, int durability, ushort type) public static InventoryItem CreateItem(uint itemId, int quantity, byte quality, byte itemType, int durability)
{ {
InventoryItem insertedItem = null; InventoryItem insertedItem = null;
@ -1303,27 +1303,52 @@ namespace FFXIVClassic_Map_Server
MySqlCommand cmd = new MySqlCommand(query, conn); MySqlCommand cmd = new MySqlCommand(query, conn);
string query2 = @"
INSERT INTO characters_inventory
(characterId, slot, inventoryType, serverItemId, quantity)
SELECT @charId, IFNULL(MAX(SLOT)+1, 0), @inventoryType, LAST_INSERT_ID(), @quantity FROM characters_inventory WHERE characterId = @charId AND inventoryType = @inventoryType;
";
MySqlCommand cmd2 = new MySqlCommand(query2, conn);
cmd.Parameters.AddWithValue("@itemId", itemId); cmd.Parameters.AddWithValue("@itemId", itemId);
cmd.Parameters.AddWithValue("@quality", quality); cmd.Parameters.AddWithValue("@quality", quality);
cmd.Parameters.AddWithValue("@itemType", itemType); cmd.Parameters.AddWithValue("@itemType", itemType);
cmd.Parameters.AddWithValue("@durability", durability); cmd.Parameters.AddWithValue("@durability", durability);
cmd2.Parameters.AddWithValue("@charId", player.actorId);
cmd2.Parameters.AddWithValue("@inventoryType", type);
cmd2.Parameters.AddWithValue("@quantity", quantity);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
cmd2.ExecuteNonQuery();
insertedItem = new InventoryItem((uint)cmd.LastInsertedId, itemId, quantity, (ushort)player.GetInventory(type).GetNextEmptySlot(), itemType, quality, durability, 0, 0, 0, 0, 0, 0); insertedItem = new InventoryItem((uint)cmd.LastInsertedId, itemId, quantity, itemType, quality, durability, 0, 0, 0, 0, 0, 0);
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
}
finally
{
conn.Dispose();
}
}
return insertedItem;
}
public static InventoryItem AddItem(Player player, InventoryItem addedItem, uint type)
{
InventoryItem insertedItem = null;
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 = @"
INSERT INTO characters_inventory
(characterId, slot, inventoryType, serverItemId, quantity)
SELECT @charId, IFNULL(MAX(SLOT)+1, 0), @inventoryType, @uid, @quantity FROM characters_inventory WHERE characterId = @charId AND inventoryType = @inventoryType;
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@uid", addedItem.uniqueId);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.Parameters.AddWithValue("@inventoryType", type);
cmd.Parameters.AddWithValue("@quantity", insertedItem.quantity);
cmd.ExecuteNonQuery();
} }
catch (MySqlException e) catch (MySqlException e)
{ {

View File

@ -106,13 +106,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
for (int i = 0; i < slots.Length; i++) for (int i = 0; i < slots.Length; i++)
{ {
InventoryItem item = normalInventory.GetItemBySlot(itemSlots[i]); InventoryItem item = normalInventory.GetItemAtSlot(itemSlots[i]);
if (item == null) if (item == null)
continue; continue;
Database.EquipItem(owner, slots[i], item.uniqueId); Database.EquipItem(owner, slots[i], item.uniqueId);
list[slots[i]] = normalInventory.GetItemBySlot(itemSlots[i]); list[slots[i]] = normalInventory.GetItemAtSlot(itemSlots[i]);
} }
owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId)); owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
@ -133,7 +133,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
public void Equip(ushort slot, ushort invSlot) public void Equip(ushort slot, ushort invSlot)
{ {
InventoryItem item = normalInventory.GetItemBySlot(invSlot); InventoryItem item = normalInventory.GetItemAtSlot(invSlot);
if (item == null) if (item == null)
return; return;

View File

@ -20,14 +20,19 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
public const ushort CURRENCY = 0x0063; //Max 0x140 public const ushort CURRENCY = 0x0063; //Max 0x140
public const ushort KEYITEMS = 0x0064; //Max 0x500 public const ushort KEYITEMS = 0x0064; //Max 0x500
public const ushort EQUIPMENT = 0x00FE; //Max 0x23 public const ushort EQUIPMENT = 0x00FE; //Max 0x23
public const ushort EQUIPMENT_OTHERPLAYER = 0x00F9; //Max 0x23 public const ushort EQUIPMENT_OTHERPLAYER = 0x00F9; //Max 0x23
private int endOfListIndex = 0;
private Player owner; private Character owner;
private List<Player> viewer;
private ushort inventoryCapacity; private ushort inventoryCapacity;
private ushort inventoryCode; private ushort inventoryCode;
private List<InventoryItem> list; private InventoryItem[] list;
private InventoryItem[] lastList;
public Inventory(Player ownerPlayer, ushort capacity, ushort code) private bool[] isDirty;
public Inventory(Character ownerPlayer, ushort capacity, ushort code)
{ {
owner = ownerPlayer; owner = ownerPlayer;
inventoryCapacity = capacity; inventoryCapacity = capacity;
@ -37,12 +42,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
#region Inventory Management #region Inventory Management
public void InitList(List<InventoryItem> itemsFromDB) public void InitList(List<InventoryItem> itemsFromDB)
{ {
list = itemsFromDB; int i = 0;
foreach (InventoryItem item in itemsFromDB)
list[i++] = item;
} }
public InventoryItem GetItemBySlot(ushort slot) public InventoryItem GetItemAtSlot(ushort slot)
{ {
if (slot < list.Count) if (slot < list.Length)
return list[slot]; return list[slot];
else else
return null; return null;
@ -66,28 +73,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
return item; return item;
} }
return null; return null;
} }
public void RefreshItem(InventoryItem item)
{
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(item);
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
public void RefreshItem(params InventoryItem[] items)
{
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(items.ToList());
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
public void RefreshItem(List<InventoryItem> items)
{
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(items);
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
}
public void AddItem(uint itemId) public void AddItem(uint itemId)
{ {
@ -105,9 +91,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
return false; return false;
ItemData gItem = Server.GetItemGamedata(itemId); ItemData gItem = Server.GetItemGamedata(itemId);
List<ushort> slotsToUpdate = new List<ushort>();
List<SubPacket> addItemPackets = new List<SubPacket>();
if (gItem == null) if (gItem == null)
{ {
Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId); Program.Log.Error("Inventory.AddItem: unable to find item %u", itemId);
@ -115,15 +99,19 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
} }
//Check if item id exists //Check if item id exists
int quantityCount = quantity; int quantityCount = quantity;
for (int i = 0; i < list.Count; i++) for (int i = 0; i < endOfListIndex; i++)
{ {
InventoryItem item = list[i]; InventoryItem item = list[i];
if (item == null)
throw new Exception("Item slot was null!!!");
if (item.itemId == itemId && item.quantity < gItem.maxStack) if (item.itemId == itemId && item.quantity < gItem.maxStack)
{ {
slotsToUpdate.Add(item.slot);
int oldQuantity = item.quantity; int oldQuantity = item.quantity;
item.quantity = Math.Min(item.quantity + quantityCount, gItem.maxStack); item.quantity = Math.Min(item.quantity + quantityCount, gItem.maxStack);
isDirty[i] = true;
quantityCount -= (gItem.maxStack - oldQuantity); quantityCount -= (gItem.maxStack - oldQuantity);
if (quantityCount <= 0) if (quantityCount <= 0)
break; break;
@ -136,68 +124,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
//If Inventory is full //If Inventory is full
//if (quantityCount > 0 && isInventoryFull()) //if (quantityCount > 0 && isInventoryFull())
// return ITEMERROR_FULL; // return ITEMERROR_FULL;
//Update lists and db
owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
//These had their quantities Changed
foreach (ushort slot in slotsToUpdate)
{
Database.SetQuantity(owner, slot, inventoryCode, list[slot].quantity);
if (inventoryCode != CURRENCY && inventoryCode != KEYITEMS)
SendInventoryPackets(list[slot]);
}
//New item that spilled over //New item that spilled over
while (quantityCount > 0) while (quantityCount > 0)
{ {
InventoryItem addedItem = Database.AddItem(owner, itemId, Math.Min(quantityCount, gItem.maxStack), quality, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode); InventoryItem addedItem = Database.CreateItem(itemId, Math.Min(quantityCount, gItem.maxStack), quality, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability);
isDirty[endOfListIndex] = true;
list[endOfListIndex++] = addedItem;
list.Add(addedItem);
if (inventoryCode != CURRENCY && inventoryCode != KEYITEMS)
SendInventoryPackets(addedItem);
quantityCount -= gItem.maxStack; quantityCount -= gItem.maxStack;
} }
if (inventoryCode == CURRENCY || inventoryCode == KEYITEMS)
SendFullInventory();
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
return true; return true;
} }
public void AddItem(uint[] itemId)
{
if (!IsSpaceForAdd(itemId[0], itemId.Length))
return;
//Update lists and db
owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
int startPos = list.Count;
//New item that spilled over
for (int i = 0; i < itemId.Length; i++)
{
ItemData gItem = Server.GetItemGamedata(itemId[i]);
InventoryItem addedItem = Database.AddItem(owner, itemId[i], 1, (byte)1, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode);
list.Add(addedItem);
}
SendInventoryPackets(startPos);
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
}
public void RemoveItem(uint itemId, int quantity) public void RemoveItem(uint itemId, int quantity)
{ {
if (!HasItem(itemId, quantity)) if (!HasItem(itemId, quantity))
@ -211,23 +151,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
//Remove as we go along //Remove as we go along
int quantityCount = quantity; int quantityCount = quantity;
ushort lowestSlot = 0; ushort lowestSlot = 0;
for (int i = list.Count - 1; i >= 0; i--) for (int i = endOfListIndex - 1; i >= 0; i--)
{ {
InventoryItem item = list[i]; InventoryItem item = list[i];
if (item == null)
throw new Exception("Item slot was null!!!");
if (item.itemId == itemId) if (item.itemId == itemId)
{ {
int oldQuantity = item.quantity; int oldQuantity = item.quantity;
//Stack nomnomed //Stack nomnomed
if (item.quantity - quantityCount <= 0) if (item.quantity - quantityCount <= 0)
{ list[i] = null;
itemsToRemove.Add(item); //Stack reduced
slotsToRemove.Add(item.slot); else
} item.quantity -= quantityCount;
else
{ isDirty[i] = true;
slotsToUpdate.Add(item.slot);
item.quantity -= quantityCount; //Stack reduced
}
quantityCount -= oldQuantity; quantityCount -= oldQuantity;
lowestSlot = item.slot; lowestSlot = item.slot;
@ -235,43 +176,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
if (quantityCount <= 0) if (quantityCount <= 0)
break; break;
} }
} }
doRealign();
for (int i = 0; i < slotsToUpdate.Count; i++)
{
Database.SetQuantity(owner, slotsToUpdate[i], inventoryCode, list[slotsToUpdate[i]].quantity);
}
int oldListSize = list.Count;
for (int i = 0; i < itemsToRemove.Count; i++)
{
Database.RemoveItem(owner, itemsToRemove[i].uniqueId, inventoryCode);
list.Remove(itemsToRemove[i]);
}
//Realign slots
for (int i = lowestSlot; i < list.Count; i++)
list[i].slot = (ushort)i;
//Added tail end items that need to be cleared for slot realignment
for (int i = oldListSize-1; i >= oldListSize - itemsToRemove.Count; i--)
{
if (!slotsToRemove.Contains((ushort)i))
slotsToRemove.Add((ushort)i);
}
owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(lowestSlot);
SendInventoryRemovePackets(slotsToRemove);
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
if (inventoryCode == NORMAL)
owner.GetEquipment().SendFullEquipment(false);
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
} }
public void RemoveItemByUniqueId(ulong itemDBId) public void RemoveItemByUniqueId(ulong itemDBId)
@ -291,58 +199,19 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
if (toDelete == null) if (toDelete == null)
return; return;
int oldListSize = list.Count; list[slot] = null;
list.RemoveAt(slot); isDirty[slot] = true;
Database.RemoveItem(owner, itemDBId, inventoryCode); doRealign();
//Realign slots
for (int i = slot; i < list.Count; i++)
list[i].slot = (ushort)i;
owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(slot);
SendInventoryRemovePackets(slot);
if (slot != oldListSize - 1)
SendInventoryRemovePackets((ushort)(oldListSize - 1));
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
if (inventoryCode == NORMAL)
owner.GetEquipment().SendFullEquipment(false);
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
} }
public void RemoveItemAtSlot(ushort slot) public void RemoveItemAtSlot(ushort slot)
{ {
if (slot >= list.Count) if (slot >= endOfListIndex)
return; return;
int oldListSize = list.Count; list[slot] = null;
list.RemoveAt((int)slot); isDirty[slot] = true;
Database.RemoveItem(owner, slot, inventoryCode); doRealign();
//Realign slots
for (int i = slot; i < list.Count; i++)
list[i].slot = (ushort)i;
owner.QueuePacket(InventoryBeginChangePacket.BuildPacket(owner.actorId));
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(slot);
SendInventoryRemovePackets(slot);
if (slot != oldListSize - 1)
SendInventoryRemovePackets((ushort)(oldListSize - 1));
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
if (inventoryCode == NORMAL)
owner.GetEquipment().SendFullEquipment(false);
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
} }
public void ChangeDurability(uint slot, uint durabilityChange) public void ChangeDurability(uint slot, uint durabilityChange)
@ -362,90 +231,92 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
#endregion #endregion
#region Packet Functions #region Packet Functions
public void SendFullInventory() public void SendFullInventory(Player player)
{ {
owner.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode)); player.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, inventoryCapacity, inventoryCode));
SendInventoryPackets(0); SendInventoryPackets(player, 0);
owner.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId)); player.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
} }
private void SendInventoryPackets(InventoryItem item) private void SendInventoryPackets(Player player, InventoryItem item)
{ {
owner.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, item)); player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, item));
} }
private void SendInventoryPackets(List<InventoryItem> items) private void SendInventoryPackets(Player player, List<InventoryItem> items)
{ {
int currentIndex = 0; int currentIndex = 0;
while (true) while (true)
{ {
if (items.Count - currentIndex >= 64) if (items.Count - currentIndex >= 64)
owner.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, items, ref currentIndex)); player.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, items, ref currentIndex));
else if (items.Count - currentIndex >= 32) else if (items.Count - currentIndex >= 32)
owner.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, items, ref currentIndex)); player.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, items, ref currentIndex));
else if (items.Count - currentIndex >= 16) else if (items.Count - currentIndex >= 16)
owner.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, items, ref currentIndex)); player.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, items, ref currentIndex));
else if (items.Count - currentIndex > 1) else if (items.Count - currentIndex > 1)
owner.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, items, ref currentIndex)); player.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, items, ref currentIndex));
else if (items.Count - currentIndex == 1) else if (items.Count - currentIndex == 1)
{ {
owner.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, items[currentIndex])); player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, items[currentIndex]));
currentIndex++; currentIndex++;
} }
else else
break; break;
} }
} }
private void SendInventoryPackets(int startOffset) private void SendInventoryPackets(Player player, int startOffset)
{ {
int currentIndex = startOffset; int currentIndex = startOffset;
List<InventoryItem> lst = new List<InventoryItem>(list);
while (true) while (true)
{ {
if (list.Count - currentIndex >= 64) if (endOfListIndex - currentIndex >= 64)
owner.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, list, ref currentIndex)); player.QueuePacket(InventoryListX64Packet.BuildPacket(owner.actorId, lst, ref currentIndex));
else if (list.Count - currentIndex >= 32) else if (endOfListIndex - currentIndex >= 32)
owner.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, list, ref currentIndex)); player.QueuePacket(InventoryListX32Packet.BuildPacket(owner.actorId, lst, ref currentIndex));
else if (list.Count - currentIndex >= 16) else if (endOfListIndex - currentIndex >= 16)
owner.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, list, ref currentIndex)); player.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, lst, ref currentIndex));
else if (list.Count - currentIndex > 1) else if (endOfListIndex - currentIndex > 1)
owner.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, list, ref currentIndex)); player.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, lst, ref currentIndex));
else if (list.Count - currentIndex == 1) else if (endOfListIndex - currentIndex == 1)
{ {
owner.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, list[currentIndex])); player.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, list[currentIndex]));
currentIndex++; currentIndex++;
} }
else else
break; break;
} }
} }
private void SendInventoryRemovePackets(ushort index) private void SendInventoryRemovePackets(Player player, ushort index)
{ {
owner.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, index)); player.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, index));
} }
private void SendInventoryRemovePackets(List<ushort> indexes) private void SendInventoryRemovePackets(Player player, List<ushort> indexes)
{ {
int currentIndex = 0; int currentIndex = 0;
while (true) while (true)
{ {
if (indexes.Count - currentIndex >= 64) if (indexes.Count - currentIndex >= 64)
owner.QueuePacket(InventoryRemoveX64Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); player.QueuePacket(InventoryRemoveX64Packet.BuildPacket(owner.actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex >= 32) else if (indexes.Count - currentIndex >= 32)
owner.QueuePacket(InventoryRemoveX32Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); player.QueuePacket(InventoryRemoveX32Packet.BuildPacket(owner.actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex >= 16) else if (indexes.Count - currentIndex >= 16)
owner.QueuePacket(InventoryRemoveX16Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); player.QueuePacket(InventoryRemoveX16Packet.BuildPacket(owner.actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex > 1) else if (indexes.Count - currentIndex > 1)
owner.QueuePacket(InventoryRemoveX08Packet.BuildPacket(owner.actorId, indexes, ref currentIndex)); player.QueuePacket(InventoryRemoveX08Packet.BuildPacket(owner.actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex == 1) else if (indexes.Count - currentIndex == 1)
{ {
owner.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, indexes[currentIndex])); player.QueuePacket(InventoryRemoveX01Packet.BuildPacket(owner.actorId, indexes[currentIndex]));
currentIndex++; currentIndex++;
} }
else else
@ -454,19 +325,47 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
} }
#endregion #endregion
#region Inventory Utils #region Client Updating
private void SendUpdatePackets(Player player)
{
List<InventoryItem> items = new List<InventoryItem>();
List<ushort> slotsToRemove = new List<ushort>();
for (int i = 0; i < list.Length; i++)
{
if (i == endOfListIndex)
break;
if (isDirty[i])
items.Add(list[i]);
}
for (int i = endOfListIndex; i < lastList.Length; i++)
{
if (lastList[i] != null)
slotsToRemove.Add((ushort)i);
}
//Send Updated Slots
SendInventoryPackets(player, items);
//Send Remove packets for tail end
SendInventoryRemovePackets(player, slotsToRemove);
}
#endregion
#region Inventory Utils
public bool IsFull() public bool IsFull()
{ {
return list.Count >= inventoryCapacity; return endOfListIndex >= inventoryCapacity;
} }
public bool IsSpaceForAdd(uint itemId, int quantity) public bool IsSpaceForAdd(uint itemId, int quantity)
{ {
int quantityCount = quantity; int quantityCount = quantity;
for (int i = 0; i < list.Count; i++) for (int i = 0; i < endOfListIndex; i++)
{ {
InventoryItem item = list[i]; InventoryItem item = list[i];
ItemData gItem = Server.GetItemGamedata(item.itemId); ItemData gItem = Server.GetItemGamedata(item.itemId);
@ -503,8 +402,33 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
} }
public int GetNextEmptySlot() public int GetNextEmptySlot()
{ {
return list.Count == 0 ? 0 : list.Count(); return endOfListIndex;
}
private void doRealign()
{
int lastNullSlot = -1;
for (int i = 0; i < endOfListIndex; i++)
{
if (list[i] == null && lastNullSlot != -1)
{
lastNullSlot = i;
continue;
}
else if (list[i] != null && lastNullSlot != -1)
{
list[lastNullSlot] = list[i];
list[lastNullSlot].slot = (ushort)lastNullSlot;
list[i] = null;
isDirty[lastNullSlot] = true;
isDirty[i] = true;
lastNullSlot++;
}
}
endOfListIndex = lastNullSlot;
} }
#endregion #endregion

View File

@ -533,12 +533,12 @@ namespace FFXIVClassic_Map_Server.Actors
#region Inventory & Equipment #region Inventory & Equipment
QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId)); QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId));
inventories[Inventory.NORMAL].SendFullInventory(); inventories[Inventory.NORMAL].SendFullInventory(this);
inventories[Inventory.CURRENCY].SendFullInventory(); inventories[Inventory.CURRENCY].SendFullInventory(this);
inventories[Inventory.KEYITEMS].SendFullInventory(); inventories[Inventory.KEYITEMS].SendFullInventory(this);
inventories[Inventory.BAZAAR].SendFullInventory(); inventories[Inventory.BAZAAR].SendFullInventory(this);
inventories[Inventory.MELDREQUEST].SendFullInventory(); inventories[Inventory.MELDREQUEST].SendFullInventory(this);
inventories[Inventory.LOOT].SendFullInventory(); inventories[Inventory.LOOT].SendFullInventory(this);
equipment.SendFullEquipment(false); equipment.SendFullEquipment(false);
playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId));
#endregion #endregion

View File

@ -23,12 +23,11 @@ namespace FFXIVClassic_Map_Server.dataobjects
public byte materia5 = 0; public byte materia5 = 0;
//Bare Minimum //Bare Minimum
public InventoryItem(uint id, uint itemId, ushort slot) public InventoryItem(uint id, uint itemId)
{ {
this.uniqueId = id; this.uniqueId = id;
this.itemId = itemId; this.itemId = itemId;
this.quantity = 1; this.quantity = 1;
this.slot = slot;
ItemData gItem = Server.GetItemGamedata(itemId); ItemData gItem = Server.GetItemGamedata(itemId);
itemType = gItem.isExclusive ? (byte)0x3 : (byte)0x0; itemType = gItem.isExclusive ? (byte)0x3 : (byte)0x0;
@ -55,12 +54,11 @@ namespace FFXIVClassic_Map_Server.dataobjects
this.materia5 = item.materia5; this.materia5 = item.materia5;
} }
public InventoryItem(uint uniqueId, uint itemId, int quantity, ushort slot, byte itemType, byte qualityNumber, int durability, ushort spiritbind, byte materia1, byte materia2, byte materia3, byte materia4, byte materia5) public InventoryItem(uint uniqueId, uint itemId, int quantity, byte itemType, byte qualityNumber, int durability, ushort spiritbind, byte materia1, byte materia2, byte materia3, byte materia4, byte materia5)
{ {
this.uniqueId = uniqueId; this.uniqueId = uniqueId;
this.itemId = itemId; this.itemId = itemId;
this.quantity = quantity; this.quantity = quantity;
this.slot = slot;
this.itemType = itemType; this.itemType = itemType;
this.quality = qualityNumber; this.quality = qualityNumber;
this.durability = durability; this.durability = durability;