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