diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index edb149f4..06fbd4e6 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -1049,40 +1049,6 @@ namespace FFXIVClassic_Map_Server return Database.CreateItem(itemId, amount, quality); } - public void AddToBazaarRewardGil(Player player, InventoryItem seek, int seekAmount, int gilAmount, byte bazaarMode) - { - bool succ = Database.CreateBazaarEntry(player, gilReward, seek, gilAmount, seekAmount, bazaarMode); - - if (succ) - { - player.GetInventory(Inventory.CURRENCY_CRYSTALS).RemoveItem(1000001, gilAmount); - player.GetInventory(Inventory.BAZAAR).StartSendUpdate(); - player.GetInventory(Inventory.BAZAAR).AddItem(gilReward); - player.GetInventory(Inventory.BAZAAR).AddItem(seek); - player.GetInventory(Inventory.BAZAAR).DoneSendUpdate(); - } - } - - public void AddToBazaarSeekGil(Player player, InventoryItem reward, int rewardAmount, int gilAmount, byte bazaarMode) - { - InventoryItem gilSeek = Database.CreateItem(1000001, gilAmount, 1); - bool succ = false; - - if (bazaarMode == InventoryItem.TYPE_SINGLE || bazaarMode == InventoryItem.TYPE_STACK) - succ = Database.CreateBazaarEntry(player, reward, gilSeek, rewardAmount, 0, bazaarMode, gilAmount); - else - succ = Database.CreateBazaarEntry(player, reward, gilSeek, rewardAmount, gilAmount, bazaarMode); - - if (succ) - { - player.GetInventory(Inventory.NORMAL).RemoveItem(reward); - player.GetInventory(Inventory.BAZAAR).StartSendUpdate(); - player.GetInventory(Inventory.BAZAAR).AddItem(reward); - player.GetInventory(Inventory.BAZAAR).AddItem(gilSeek); - player.GetInventory(Inventory.BAZAAR).DoneSendUpdate(); - } - } - public void AddToBazaar(Player player, InventoryItem reward, InventoryItem seek, int rewardAmount, int seekAmount, byte bazaarMode) { bool succ = Database.CreateBazaarEntry(player, reward, seek, rewardAmount, seekAmount, bazaarMode); @@ -1090,9 +1056,13 @@ namespace FFXIVClassic_Map_Server if (succ) { if (reward.GetItemData().IsMoney()) + player.RemoveItem(1000001, rewardAmount); + else + player.RemoveItem(reward, rewardAmount); + + if (!reward.GetItemData().IsMoney()) + player.RemoveItem(seek, seekAmount); - player.GetInventory(Inventory.NORMAL).RemoveItem(reward); - player.GetInventory(Inventory.NORMAL).RemoveItem(seek); player.GetInventory(Inventory.BAZAAR).StartSendUpdate(); player.GetInventory(Inventory.BAZAAR).AddItem(reward); player.GetInventory(Inventory.BAZAAR).AddItem(seek); diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index 6d56209e..e9057033 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -1,9 +1,12 @@  using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.actors.chara.player; using FFXIVClassic_Map_Server.actors.group; using FFXIVClassic_Map_Server.Actors.Chara; +using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.utils; +using System.Collections.Generic; namespace FFXIVClassic_Map_Server.Actors { @@ -56,6 +59,10 @@ namespace FFXIVClassic_Map_Server.Actors public Group currentParty = null; public ContentGroup currentContentGroup = null; + //Inventory + protected Dictionary itemPackages = new Dictionary(); + private Equipment equipment; + public Character(uint actorID) : base(actorID) { //Init timer array to "notimer" @@ -114,6 +121,162 @@ namespace FFXIVClassic_Map_Server.Actors else zone.BroadcastPacketAroundActor(this, PlayAnimationOnActorPacket.BuildPacket(actorId, animId)); } + + #region Inventory + + public void AddItem(uint catalogID) + { + AddItem(catalogID, 1); + } + + public void AddItem(uint catalogID, int quantity) + { + AddItem(catalogID, quantity, 1); + } + + public void AddItem(uint catalogID, int quantity, byte quality) + { + ushort itemPackage = GetPackageForItem(catalogID); + if (itemPackages.ContainsKey(itemPackage)) + { + InventoryItem item = Server.GetWorldManager().CreateItem(catalogID, quantity, quality); + itemPackages[itemPackage].AddItem(item); + } + } + + public void AddItem(InventoryItem item) + { + ushort itemPackage = GetPackageForItem(item.GetItemData().catalogID); + if (itemPackages.ContainsKey(itemPackage)) + { + itemPackages[itemPackage].AddItem(item); + } + } + + public void SetItem(InventoryItem item, ushort itemPackage, ushort slot) + { + if (itemPackages.ContainsKey(itemPackage)) + { + itemPackages[itemPackage].AddItemSpecial(slot, item); + } + } + + public void MoveItem(InventoryItem item, ushort destinationPackage) + { + ushort sourcePackage = item.itemPackage; + + if (!itemPackages.ContainsKey(sourcePackage) && !itemPackages.ContainsKey(destinationPackage)) + return; + + itemPackages[sourcePackage].RemoveItem(item); + itemPackages[destinationPackage].AddItem(item); + } + + public void RemoveItem(uint catalogID) + { + RemoveItem(catalogID, 1); + } + + public void RemoveItem(uint catalogID, int quantity) + { + RemoveItem(catalogID, quantity, 1); + } + + public void RemoveItem(uint catalogID, int quantity, byte quality) + { + ushort itemPackage = GetPackageForItem(catalogID); + if (itemPackages.ContainsKey(itemPackage)) + { + itemPackages[itemPackage].RemoveItem(catalogID, quantity, quantity); + } + } + + public void RemoveItemAtSlot(ushort itemPackage, ushort slot) + { + if (itemPackages.ContainsKey(itemPackage)) + { + itemPackages[itemPackage].RemoveItemAtSlot(slot); + } + } + + public void RemoveItem(InventoryItem item) + { + RemoveItem(item, 1); + } + + public void RemoveItem(InventoryItem item, int quantity) + { + if (itemPackages.ContainsKey(item.itemPackage)) + { + itemPackages[item.itemPackage].RemoveItem(item, quantity); + } + } + + public bool HasItem(uint catalogID) + { + return HasItem(catalogID, 1); + } + + public bool HasItem(uint catalogID, int minQuantity) + { + return HasItem(catalogID, minQuantity, 1); + } + + public bool HasItem(uint catalogID, int minQuantity, byte quality) + { + ushort itemPackage = GetPackageForItem(catalogID); + if (itemPackages.ContainsKey(itemPackage)) + { + itemPackages[itemPackage].HasItem(catalogID, minQuantity, quality); + } + return false; + } + + public bool HasItem(InventoryItem item) + { + ushort itemPackage = GetPackageForItem(item.GetItemData().catalogID); + if (itemPackages.ContainsKey(itemPackage)) + { + //return itemPackages[itemPackage].HasItem(item); + return false; //TODO FIX + } + return false; + } + + public InventoryItem GetItem(LuaUtils.ItemRefParam reference) + { + if (reference.actorId != actorId) + return null; + if (itemPackages.ContainsKey(reference.itemPackage)) + { + return itemPackages[reference.itemPackage].GetItemAtSlot(reference.slot); + } + return null; + } + + public ushort GetPackageForItem(uint catalogID) + { + ItemData data = Server.GetItemGamedata(catalogID); + + if (data == null) + return Inventory.NORMAL; + else + { + if (data.IsMoney()) + return Inventory.CURRENCY_CRYSTALS; + else if (data.IsImportant()) + return Inventory.KEYITEMS; + else + return Inventory.NORMAL; + } + } + + #endregion + + //public void removeItem(byUniqueId) + //public void removeItem(byUniqueId, quantity) + //public void removeItem(slot) + //public void removeItem(slot, quantity) } diff --git a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs index aadcf9bd..76c19af9 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Inventory.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Inventory.cs @@ -126,6 +126,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.player return INV_ERROR.SYSTEM_ERROR; } + itemRef.RefreshPositioning(inventoryCode, (ushort) endOfListIndex); + isDirty[endOfListIndex] = true; list[endOfListIndex++] = itemRef; DoDatabaseAdd(itemRef); @@ -265,10 +267,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.player public void RemoveItem(InventoryItem item) { - RemoveItemByUniqueId(item.uniqueId); - } - - public void RemoveItemByUniqueId(ulong itemDBId) + RemoveItemByUniqueId(item.uniqueId, 1); + } + + public void RemoveItem(InventoryItem item, int quantity) + { + RemoveItemByUniqueId(item.uniqueId, quantity); + } + + public void RemoveItemByUniqueId(ulong itemDBId, int quantity) { ushort slot = 0; InventoryItem toDelete = null; @@ -288,10 +295,18 @@ namespace FFXIVClassic_Map_Server.actors.chara.player if (toDelete == null) return; + + if (quantity >= toDelete.quantity) + { + DoDatabaseRemove(toDelete.uniqueId); + list[slot] = null; + } + else + { + list[slot].quantity -= quantity; + //DoDatabaseUpdateQuantity(toDelete.uniqueId); + } - DoDatabaseRemove(toDelete.uniqueId); - - list[slot] = null; isDirty[slot] = true; DoRealign(); diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 5d10846c..c151b25a 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -104,10 +104,6 @@ namespace FFXIVClassic_Map_Server.Actors public bool isGM = false; public bool isZoneChanging = true; - //Inventory - private Dictionary inventories = new Dictionary(); - private Equipment equipment; - //Trading private Player otherTrader = null; private Inventory myOfferings; @@ -172,14 +168,14 @@ namespace FFXIVClassic_Map_Server.Actors moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN; moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_ACTIVE; - inventories[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL); - inventories[Inventory.KEYITEMS] = new Inventory(this, MAXSIZE_INVENTORY_KEYITEMS, Inventory.KEYITEMS); - inventories[Inventory.CURRENCY_CRYSTALS] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRENCY_CRYSTALS); - inventories[Inventory.MELDREQUEST] = new Inventory(this, MAXSIZE_INVENTORY_MELDREQUEST, Inventory.MELDREQUEST); - inventories[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR); - inventories[Inventory.LOOT] = new Inventory(this, MAXSIZE_INVENTORY_LOOT, Inventory.LOOT); + itemPackages[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL); + itemPackages[Inventory.KEYITEMS] = new Inventory(this, MAXSIZE_INVENTORY_KEYITEMS, Inventory.KEYITEMS); + itemPackages[Inventory.CURRENCY_CRYSTALS] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRENCY_CRYSTALS); + itemPackages[Inventory.MELDREQUEST] = new Inventory(this, MAXSIZE_INVENTORY_MELDREQUEST, Inventory.MELDREQUEST); + itemPackages[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR); + itemPackages[Inventory.LOOT] = new Inventory(this, MAXSIZE_INVENTORY_LOOT, Inventory.LOOT); - equipment = new Equipment(this, inventories[Inventory.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, Inventory.EQUIPMENT); + equipment = new Equipment(this, itemPackages[Inventory.NORMAL], MAXSIZE_INVENTORY_EQUIPMENT, Inventory.EQUIPMENT); //Set the Skill level caps of all FFXIV (classes)skills to 50 for (int i = 0; i < charaWork.battleSave.skillLevelCap.Length; i++) @@ -559,12 +555,12 @@ namespace FFXIVClassic_Map_Server.Actors #region Inventory & Equipment QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId)); - inventories[Inventory.NORMAL].SendFullInventory(this); - inventories[Inventory.CURRENCY_CRYSTALS].SendFullInventory(this); - inventories[Inventory.KEYITEMS].SendFullInventory(this); - inventories[Inventory.BAZAAR].SendFullInventory(this); - inventories[Inventory.MELDREQUEST].SendFullInventory(this); - inventories[Inventory.LOOT].SendFullInventory(this); + itemPackages[Inventory.NORMAL].SendFullInventory(this); + itemPackages[Inventory.CURRENCY_CRYSTALS].SendFullInventory(this); + itemPackages[Inventory.KEYITEMS].SendFullInventory(this); + itemPackages[Inventory.BAZAAR].SendFullInventory(this); + itemPackages[Inventory.MELDREQUEST].SendFullInventory(this); + itemPackages[Inventory.LOOT].SendFullInventory(this); equipment.SendFullEquipment(false); playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); #endregion @@ -1106,8 +1102,8 @@ namespace FFXIVClassic_Map_Server.Actors public Inventory GetInventory(ushort type) { - if (inventories.ContainsKey(type)) - return inventories[type]; + if (itemPackages.ContainsKey(type)) + return itemPackages[type]; else return null; } @@ -1891,7 +1887,7 @@ namespace FFXIVClassic_Map_Server.Actors if (!IsTrading()) return; - InventoryItem mine = inventories[Inventory.NORMAL].GetItemAtSlot(linkedSlot); + InventoryItem mine = itemPackages[Inventory.NORMAL].GetItemAtSlot(linkedSlot); InventoryItem tradeItem = new InventoryItem(mine, slot); @@ -1948,7 +1944,6 @@ namespace FFXIVClassic_Map_Server.Actors otherTrader = null; } - public void Test() { QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId)); diff --git a/FFXIVClassic Map Server/dataobjects/InventoryItem.cs b/FFXIVClassic Map Server/dataobjects/InventoryItem.cs index 71c66a44..dfbdd894 100644 --- a/FFXIVClassic Map Server/dataobjects/InventoryItem.cs +++ b/FFXIVClassic Map Server/dataobjects/InventoryItem.cs @@ -21,7 +21,6 @@ namespace FFXIVClassic_Map_Server.dataobjects public ulong uniqueId; public uint itemId; public int quantity = 1; - public ushort slot; public byte dealingVal = 0; public byte dealingMode = DEALINGMODE_NONE; @@ -39,6 +38,8 @@ namespace FFXIVClassic_Map_Server.dataobjects public ItemModifier modifiers; public readonly ItemData itemData; + public ushort slot; + public ushort itemPackage; public class ItemModifier { @@ -195,6 +196,12 @@ namespace FFXIVClassic_Map_Server.dataobjects return data; } + public void RefreshPositioning(ushort itemPackage, ushort slot) + { + this.itemPackage = itemPackage; + this.slot = slot; + } + public void SetExclusive(bool isExclusive) { tags[1] = isExclusive ? TAG_EXCLUSIVE : (byte)0; diff --git a/FFXIVClassic Map Server/lua/LuaUtils.cs b/FFXIVClassic Map Server/lua/LuaUtils.cs index a0eb86a2..861f8159 100644 --- a/FFXIVClassic Map Server/lua/LuaUtils.cs +++ b/FFXIVClassic Map Server/lua/LuaUtils.cs @@ -12,19 +12,19 @@ namespace FFXIVClassic_Map_Server class LuaUtils { - public class Type7Param + public class ItemRefParam { public uint actorId; public byte unknown; public byte slot; - public byte inventoryType; + public byte itemPackage; - public Type7Param(uint actorId, byte unknown, byte slot, byte inventoryType) + public ItemRefParam(uint actorId, byte unknown, byte slot, byte itemPackage) { this.actorId = actorId; this.unknown = unknown; this.slot = slot; - this.inventoryType = inventoryType; + this.itemPackage = itemPackage; } } @@ -86,7 +86,7 @@ namespace FFXIVClassic_Map_Server byte type7Unknown = reader.ReadByte(); byte type7Slot = reader.ReadByte(); byte type7InventoryType = reader.ReadByte(); - value = new Type7Param(type7ActorId, type7Unknown, type7Slot, type7InventoryType); + value = new ItemRefParam(type7ActorId, type7Unknown, type7Slot, type7InventoryType); break; case 0x9: //Two Longs (only storing first one) value = new Type9Param(Utils.SwapEndian(reader.ReadUInt64()), Utils.SwapEndian(reader.ReadUInt64())); @@ -146,11 +146,11 @@ namespace FFXIVClassic_Map_Server writer.Write((UInt32)Utils.SwapEndian((UInt32)l.value)); break; case 0x7: //Weird one used for inventory - Type7Param type7 = (Type7Param)l.value; + ItemRefParam type7 = (ItemRefParam)l.value; writer.Write((UInt32)Utils.SwapEndian((UInt32)type7.actorId)); writer.Write((Byte)type7.unknown); writer.Write((Byte)type7.slot); - writer.Write((Byte)type7.inventoryType); + writer.Write((Byte)type7.itemPackage); break; case 0x9: //Two Longs (only storing first one) writer.Write((UInt64)Utils.SwapEndian(((Type9Param)l.value).item1)); @@ -220,7 +220,7 @@ namespace FFXIVClassic_Map_Server byte type7Unknown = reader.ReadByte(); byte type7Slot = reader.ReadByte(); byte type7InventoryType = reader.ReadByte(); - value = new Type7Param(type7ActorId, type7Unknown, type7Slot, type7InventoryType); + value = new ItemRefParam(type7ActorId, type7Unknown, type7Slot, type7InventoryType); break; case 0x9: //Two Longs (only storing first one) value = new Type9Param(Utils.SwapEndian(reader.ReadUInt64()), Utils.SwapEndian(reader.ReadUInt64())); @@ -353,9 +353,9 @@ namespace FFXIVClassic_Map_Server { luaParams.Add(new LuaParam(0x6, ((Actor)o).actorId)); } - else if (o is Type7Param) + else if (o is ItemRefParam) { - luaParams.Add(new LuaParam(0x7, (Type7Param)o)); + luaParams.Add(new LuaParam(0x7, (ItemRefParam)o)); } else if (o is Type9Param) { @@ -410,8 +410,8 @@ namespace FFXIVClassic_Map_Server dumpString += String.Format("0x{0:X}", (uint)lParams[i].value); break; case 0x7: //Weird one used for inventory - Type7Param type7Param = ((Type7Param)lParams[i].value); - dumpString += String.Format("Type7 Param: (0x{0:X}, 0x{1:X}, 0x{2:X}, 0x{3:X})", type7Param.actorId, type7Param.unknown, type7Param.slot, type7Param.inventoryType); + ItemRefParam type7Param = ((ItemRefParam)lParams[i].value); + dumpString += String.Format("Type7 Param: (0x{0:X}, 0x{1:X}, 0x{2:X}, 0x{3:X})", type7Param.actorId, type7Param.unknown, type7Param.slot, type7Param.itemPackage); break; case 0xC: //Byte dumpString += String.Format("0x{0:X}", (byte)lParams[i].value);