Added all the inventory packets, and implemented add and get inventory from the db to the server. Inventory at login is now connected to the db!

This commit is contained in:
Filip Maj 2016-02-11 22:14:40 -05:00
parent c4dea467e3
commit df2ac1fb32
23 changed files with 1227 additions and 160 deletions

View File

@ -19,7 +19,7 @@ namespace FFXIVClassic_Lobby_Server
//Connection stuff
public Blowfish blowfish;
public Socket socket;
public byte[] buffer = new byte[0xffff];
public byte[] buffer = new byte[0xfffff];
private BlockingCollection<BasePacket> sendPacketQueue = new BlockingCollection<BasePacket>(1000);
//Instance Stuff
@ -46,7 +46,7 @@ namespace FFXIVClassic_Lobby_Server
BasePacket packet = sendPacketQueue.Take();
byte[] packetBytes = packet.getPacketBytes();
byte[] buffer = new byte[0xffff];
byte[] buffer = new byte[0xfffff];
Array.Copy(packetBytes, buffer, packetBytes.Length);
try
{

View File

@ -14,6 +14,8 @@ using FFXIVClassic_Lobby_Server.dataobjects;
using FFXIVClassic_Map_Server;
using FFXIVClassic_Map_Server.common.EfficientHashTables;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
namespace FFXIVClassic_Lobby_Server
{
@ -449,6 +451,202 @@ namespace FFXIVClassic_Lobby_Server
}
}
player.invNormal = getInventory(player, 0, InventorySetBeginPacket.CODE_INVENTORY);
player.invKeyItems = getInventory(player, 0, InventorySetBeginPacket.CODE_KEYITEMS);
player.invCurrancy = getInventory(player, 0, InventorySetBeginPacket.CODE_CURRANCY);
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Dispose();
}
}
}
public static List<Item> getInventory(Player player, uint slotOffset, uint type)
{
List<Item> items = new List<Item>();
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();
//Load Last 5 Completed
string query = @"
SELECT
serverItemId,
itemId,
quantity,
slot,
isUntradeable,
quality,
durability,
spiritBind,
materia1,
materia2,
materia3,
materia4,
materia5
FROM characters_inventory
INNER JOIN server_items ON serverItemId = server_items.id
WHERE characterId = @charId AND inventoryType = @type AND slot >= @slot ORDER BY slot";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.Parameters.AddWithValue("@slot", slotOffset);
cmd.Parameters.AddWithValue("@type", type);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
uint uniqueId = reader.GetUInt32(0);
uint itemId = reader.GetUInt32(1);
int quantity = reader.GetInt32(2);
uint slot = reader.GetUInt32(3);
bool isUntradeable = reader.GetBoolean(4);
byte qualityNumber = reader.GetByte(5);
uint durability = reader.GetUInt32(6);
ushort spiritBind = reader.GetUInt16(7);
byte materia1 = reader.GetByte(8);
byte materia2 = reader.GetByte(9);
byte materia3 = reader.GetByte(10);
byte materia4 = reader.GetByte(11);
byte materia5 = reader.GetByte(12);
items.Add(new Item(uniqueId, itemId, quantity, slot, isUntradeable, qualityNumber, durability, spiritBind, materia1, materia2, materia3, materia4, materia5));
}
}
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Dispose();
}
}
return items;
}
public static Item addItem(Player player, uint itemId, int quantity, byte quality, bool isUntradeable, uint durability, ushort type)
{
Item 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 server_items
(itemId, quality, isUntradeable, durability)
VALUES
(@itemId, @quality, @isUntradeable, @durability);
";
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;
";
query += query2;
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.Parameters.AddWithValue("@inventoryType", type);
cmd.Parameters.AddWithValue("@itemId", itemId);
cmd.Parameters.AddWithValue("@quantity", quantity);
cmd.Parameters.AddWithValue("@quality", quality);
cmd.Parameters.AddWithValue("@isUntradeable", isUntradeable);
cmd.Parameters.AddWithValue("@durability", durability);
cmd.ExecuteNonQuery();
insertedItem = new Item((uint)cmd.LastInsertedId, itemId, quantity, (uint)player.getLastInventorySlot(type), isUntradeable, quality, durability, 0, 0, 0, 0, 0, 0);
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Dispose();
}
}
return insertedItem;
}
public static void addQuantity(Player player, uint itemId, 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 characters_inventory
SET quantity = quantity + @quantity
WHERE serverItemId = (SELECT id FROM server_items WHERE characterId = @charId AND itemId = @itemId LIMIT 1)
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.Parameters.AddWithValue("@quantity", quantity);
cmd.Parameters.AddWithValue("@itemId", itemId);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Dispose();
}
}
}
public static void removeItem(Player player, uint uniqueItemId)
{
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();
//Load Last 5 Completed
string query = @"
DELETE FROM server_items
WHERE id = @uniqueItemId;
";
string query2 = @"
DELETE FROM character_inventory
WHERE uniqueServerId = @uniqueItemId;
UPDATE character_inventory
SET slot = slot - 1
WHERE characterId = @charId AND slot > X
";
query += query2;
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charId", player.actorId);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{ Console.WriteLine(e); }

View File

@ -125,6 +125,7 @@
<Compile Include="packets\send\actor\ActorInstantiatePacket.cs" />
<Compile Include="packets\send\actor\BattleAction1Packet.cs" />
<Compile Include="packets\send\actor\battle\BattleAction.cs" />
<Compile Include="packets\send\actor\battle\BattleActionX00Packet.cs" />
<Compile Include="packets\send\actor\battle\BattleActionX18Packet.cs" />
<Compile Include="packets\send\actor\battle\BattleActionX10Packet.cs" />
<Compile Include="packets\send\actor\DeleteAllActorsPacket.cs" />
@ -135,17 +136,30 @@
<Compile Include="packets\send\actor\events\SetEmoteEventCondition.cs" />
<Compile Include="packets\send\actor\events\SetTalkEventCondition.cs" />
<Compile Include="packets\send\actor\events\SetPushEventConditionWithCircle.cs" />
<Compile Include="packets\send\actor\inventory\InventoryRemoveX01Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryRemoveX08Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryRemoveX16Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryRemoveX32Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryRemoveX64Packet.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentListX64Packet.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentListX32Packet.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentListX16Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryListX01Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryListX08Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryListX16Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryListX64Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryListX32Packet.cs" />
<Compile Include="packets\send\actor\_0x132Packet.cs" />
<Compile Include="packets\send\actor\SetActorIsZoningPacket.cs" />
<Compile Include="packets\send\actor\battle\BattleActionX01Packet.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentChangePacket.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentListX01Packet.cs" />
<Compile Include="packets\send\actor\inventory\InventoryBeginChangePacket.cs" />
<Compile Include="packets\send\actor\inventory\InventoryEndChangePacket.cs" />
<Compile Include="packets\send\actor\inventory\InventoryItemEndPacket.cs" />
<Compile Include="packets\send\actor\inventory\InventoryItemPacket.cs" />
<Compile Include="packets\send\actor\inventory\InventorySetBeginPacket.cs" />
<Compile Include="packets\send\actor\inventory\InventorySetEndPacket.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentSetupPacket.cs" />
<Compile Include="packets\send\actor\inventory\EquipmentListX08Packet.cs" />
<Compile Include="packets\send\actor\RemoveActorPacket.cs" />
<Compile Include="packets\send\actor\SetActorIconPacket.cs" />
<Compile Include="packets\send\actor\SetActorIdleAnimationPacket.cs" />

View File

@ -406,6 +406,23 @@ namespace FFXIVClassic_Lobby_Server
}
}
private void giveItem(ConnectedPlayer client, uint itemId)
{
if (client != null)
{
Player p = client.getActor();
p.addItem(itemId, 0, 1, 1);
}
else
{
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
{
Player p = entry.Value.getActor();
p.addItem(itemId, 0, 1, 1);
}
}
}
internal void doCommand(string input, ConnectedPlayer client)
{
input.Trim();
@ -451,6 +468,17 @@ namespace FFXIVClassic_Lobby_Server
Log.error("Could not load packet: " + e);
}
}
else if (split[0].Equals("giveitem"))
{
try
{
giveItem(client, UInt32.Parse(split[1]));
}
catch (Exception e)
{
Log.error("Could not give item.");
}
}
else if (split[0].Equals("music"))
{
try

View File

@ -7,6 +7,7 @@ using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
using FFXIVClassic_Map_Server.packets.send.events;
using FFXIVClassic_Map_Server.packets.send.list;
@ -24,6 +25,13 @@ namespace FFXIVClassic_Map_Server.Actors
{
class Player : Character
{
public const int MAXSIZE_INVENTORY_NORMAL = 200;
public const int MAXSIZE_INVENTORY_CURRANCY = 320;
public const int MAXSIZE_INVENTORY_KEYITEMS = 500;
public const int MAXSIZE_INVENTORY_LOOT = 10;
public const int MAXSIZE_INVENTORY_MELDREQUEST = 4;
public const int MAXSIZE_INVENTORY_BAZAAR = 10;
public const int MAXSIZE_INVENTORY_EQUIPMENT = 10;
public const int TIMER_TOTORAK = 0;
public const int TIMER_DZEMAEL = 1;
@ -46,11 +54,20 @@ namespace FFXIVClassic_Map_Server.Actors
public const int TIMER_RETURN = 18;
public const int TIMER_SKIRMISH = 19;
//Player Info
public uint[] timers = new uint[20];
public ushort currentJob;
public uint currentTitle;
//Inventory
public List<Item> invNormal = new List<Item>();
public List<Item> invCurrancy = new List<Item>();
public List<Item> invKeyItems = new List<Item>();
public List<Item> invLoot = new List<Item>();
public List<Item> invMeldRequest = new List<Item>();
public List<Item> invBazaar = new List<Item>();
public int[] invEquipment = new int[MAXSIZE_INVENTORY_EQUIPMENT];
//GC Related
public byte gcCurrent;
public byte gcRankLimsa;
@ -105,6 +122,9 @@ namespace FFXIVClassic_Map_Server.Actors
charaWork.command[14] = 0xA0F00000 | 29497;
charaWork.command[15] = 0xA0F00000 | 22015;
charaWork.command[32] = 0xA0F00000 | 27191;
charaWork.command[33] = 0xA0F00000 | 22302;
charaWork.command[34] = 0xA0F00000 | 28466;
charaWork.commandAcquired[27150 - 26000] = true;
@ -124,12 +144,18 @@ namespace FFXIVClassic_Map_Server.Actors
charaWork.commandCategory[0] = 1;
charaWork.commandCategory[1] = 1;
charaWork.commandCategory[32] = 1;
charaWork.commandCategory[33] = 1;
charaWork.commandCategory[34] = 1;
charaWork.parameterSave.commandSlot_compatibility[0] = true;
charaWork.parameterSave.commandSlot_compatibility[1] = true;
charaWork.parameterSave.commandSlot_compatibility[32] = true;
charaWork.commandBorder = 0x20;
charaWork.parameterTemp.tp = 3000;
Database.loadPlayerCharacter(this);
}
@ -279,7 +305,7 @@ namespace FFXIVClassic_Map_Server.Actors
propPacketUtil.addProperty(String.Format("charaWork.command[{0}]", i));
}
/*
for (int i = 0; i < charaWork.commandCategory.Length; i++)
{
charaWork.commandCategory[i] = 1;
@ -292,7 +318,7 @@ namespace FFXIVClassic_Map_Server.Actors
if (charaWork.commandAcquired[i] != false)
propPacketUtil.addProperty(String.Format("charaWork.commandAcquired[{0}]", i));
}
*/
for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++)
{
@ -379,11 +405,11 @@ namespace FFXIVClassic_Map_Server.Actors
public void sendZoneInPackets(WorldManager world, ushort spawnType)
{
playerSession.queuePacket(SetMapPacket.buildPacket(actorId, zone.regionId, zone.actorId), true, false);
playerSession.queuePacket(SetMusicPacket.buildPacket(actorId, zone.bgmDay, 0x01), true, false);
playerSession.queuePacket(SetWeatherPacket.buildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR), true, false);
queuePacket(SetMapPacket.buildPacket(actorId, zone.regionId, zone.actorId));
queuePacket(SetMusicPacket.buildPacket(actorId, zone.bgmDay, 0x01));
queuePacket(SetWeatherPacket.buildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR));
playerSession.queuePacket(getSpawnPackets(actorId, spawnType));
queuePacket(getSpawnPackets(actorId, spawnType));
#region grouptest
//Retainers
@ -405,23 +431,27 @@ namespace FFXIVClassic_Map_Server.Actors
#region itemsetup
////////ITEMS////////
playerSession.queuePacket(InventoryBeginChangePacket.buildPacket(actorId), true, false);
queuePacket(InventoryBeginChangePacket.buildPacket(actorId));
queuePacket(InventorySetBeginPacket.buildPacket(actorId, 200, InventorySetBeginPacket.CODE_INVENTORY));
sendInventoryPackets(invNormal);
queuePacket(InventorySetEndPacket.buildPacket(actorId));
/*
//TEST
List<Item> items = new List<Item>();
items.Add(new Item(1337, 8030920, 5)); //Leather Jacket
items.Add(new Item(1337, 8030920, 0)); //Leather Jacket
items.Add(new Item(1338, 8013626, 1)); //Chocobo Mask
items.Add(new Item(1339, 5030402, 2)); //Thyrus
items.Add(new Item(1340, 8013635, 3)); //Dalamud Horn
items.Add(new Item(1341, 10100132, 4)); //Savage Might 4
items.Add(new Item(1342, 8032407, 6)); //Green Summer Halter (Female)
items.Add(new Item(1343, 8051307, 7)); //Green Summer Tanga (Female)
items.Add(new Item(1344, 8050766, 8)); //Flame Private's Saroul
items.Add(new Item(1342, 8032407, 5)); //Green Summer Halter (Female)
//items.Add(new Item(1343, 8051307, 6)); //Green Summer Tanga (Female)
int count = 0;
items[2].isHighQuality = true;
items[2].quality = 2;
items[0].durability = 9999;
items[0].spiritbind = 10000;
items[0].materia1 = 6;
@ -434,34 +464,36 @@ namespace FFXIVClassic_Map_Server.Actors
items[3].durability = 9999;
items[4].quantity = 99;
//Reused
SubPacket endInventory = InventorySetEndPacket.buildPacket(actorId);
SubPacket beginInventory = InventorySetBeginPacket.buildPacket(actorId, 200, 00);
SubPacket setInventory = InventoryItemPacket.buildPacket(actorId, items, ref count);
List<SubPacket> packets = new List<SubPacket>();
packets.Add(InventorySetBeginPacket.buildPacket(actorId, 200, InventorySetBeginPacket.CODE_INVENTORY));
packets.Add(InventoryListX08Packet.buildPacket(actorId, items,ref count));
packets.Add(InventorySetEndPacket.buildPacket(actorId));
List<SubPacket> setinvPackets = new List<SubPacket>();
setinvPackets.Add(beginInventory);
setinvPackets.Add(setInventory);
setinvPackets.Add(endInventory);
Item i = new Item(1343, 8051307, 0);
//client.queuePacket(currancy);
//client.queuePacket(keyitems);
packets.Add(InventorySetBeginPacket.buildPacket(actorId, 0x500, InventorySetBeginPacket.CODE_KEYITEMS));
packets.Add(InventoryListX01Packet.buildPacket(actorId, i));
packets.Add(InventorySetEndPacket.buildPacket(actorId));
BasePacket testPacket = BasePacket.createPacket(packets, true, false);
testPacket.debugPrintPacket();
playerSession.queuePacket(testPacket);
*/
#endregion
#region equipsetup
playerSession.queuePacket(BasePacket.createPacket(setinvPackets, true, false));
EquipmentSetupPacket initialEqupmentPacket = new EquipmentSetupPacket();
initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_BODY, 5);
initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_HEAD, 3);
initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERSHIRT, 6);
initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_UNDERGARMENT, 7);
initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_MAINHAND, 2);
initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_LEGS, 8);
EquipmentListX08Packet initialEqupmentPacket = new EquipmentListX08Packet();
initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_BODY, 5);
initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_HEAD, 3);
initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_UNDERSHIRT, 6);
initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_UNDERGARMENT, 7);
initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_MAINHAND, 2);
initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_LEGS, 8);
//Equip Init
playerSession.queuePacket(InventorySetBeginPacket.buildPacket(actorId, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false);
playerSession.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(actorId), true, false));
playerSession.queuePacket(InventorySetEndPacket.buildPacket(actorId), true, false);
// playerSession.queuePacket(InventorySetBeginPacket.buildPacket(actorId, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false);
// playerSession.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(actorId), true, false));
// playerSession.queuePacket(InventorySetEndPacket.buildPacket(actorId), true, false);
playerSession.queuePacket(InventoryEndChangePacket.buildPacket(actorId), true, false);
////////ITEMS////////
@ -488,118 +520,89 @@ namespace FFXIVClassic_Map_Server.Actors
}
private void sendInventoryPackets(Item item)
{
queuePacket(InventoryListX01Packet.buildPacket(actorId, item));
}
private void sendInventoryPackets(List<Item> items)
{
int currentIndex = 0;
while (true)
{
if (items.Count - currentIndex >= 64)
queuePacket(InventoryListX64Packet.buildPacket(actorId, items, ref currentIndex));
else if (items.Count - currentIndex >= 32)
queuePacket(InventoryListX32Packet.buildPacket(actorId, items, ref currentIndex));
else if (items.Count - currentIndex >= 16)
queuePacket(InventoryListX16Packet.buildPacket(actorId, items, ref currentIndex));
else if (items.Count - currentIndex <= 8 && items.Count - currentIndex > 1)
queuePacket(InventoryListX08Packet.buildPacket(actorId, items, ref currentIndex));
else if (items.Count - currentIndex == 1)
{
queuePacket(InventoryListX01Packet.buildPacket(actorId, items[currentIndex]));
currentIndex++;
}
else
break;
}
}
private void sendRemoveInventoryPackets(List<ushort> slots)
{
int currentIndex = 0;
while (true)
{
if (slots.Count - currentIndex >= 64)
queuePacket(InventoryRemoveX64Packet.buildPacket(actorId, slots, ref currentIndex));
else if (slots.Count - currentIndex >= 32)
queuePacket(InventoryRemoveX32Packet.buildPacket(actorId, slots, ref currentIndex));
else if (slots.Count - currentIndex >= 16)
queuePacket(InventoryRemoveX16Packet.buildPacket(actorId, slots, ref currentIndex));
else if (slots.Count - currentIndex >= 8)
queuePacket(InventoryRemoveX08Packet.buildPacket(actorId, slots, ref currentIndex));
else if (slots.Count - currentIndex == 1)
queuePacket(InventoryRemoveX01Packet.buildPacket(actorId, slots[currentIndex]));
else
break;
}
}
/*
private void sendEquipmentPackets(List<int> indexes)
{
int currentIndex = 0;
InventorySetBeginPacket.buildPacket(actorId, MAXSIZE_INVENTORY_EQUIPMENT, InventorySetBeginPacket.CODE_EQUIPMENT);
while (true)
{
if (indexes.Count - currentIndex >= 64)
queuePacket(EquipmentListX64Packet.buildPacket(actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex >= 32)
queuePacket(EquipmentListX32Packet.buildPacket(actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex >= 16)
queuePacket(EquipmentListX16Packet.buildPacket(actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex >= 8)
queuePacket(EquipmentListX08Packet.buildPacket(actorId, indexes, ref currentIndex));
else if (indexes.Count - currentIndex == 1)
queuePacket(EquipmentListX01Packet.buildPacket(actorId, indexes[currentIndex]));
else
break;
}
InventorySetEndPacket.buildPacket(actorId);
}
*/
public bool isMyPlayer(uint otherActorId)
{
return actorId == otherActorId;
}
public void loadNpcTemplate(uint id)
{
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 = @"
SELECT
displayNameId,
customDisplayName,
base,
size,
hairStyle,
hairHighlightColor,
hairVariation,
faceType,
characteristics,
characteristicsColor,
faceEyebrows,
faceIrisSize,
faceEyeShape,
faceNose,
faceFeatures,
faceMouth,
ears,
hairColor,
skinColor,
eyeColor,
voice,
mainHand,
offHand,
spMainHand,
spOffHand,
throwing,
pack,
pouch,
head,
body,
legs,
hands,
feet,
waist,
neck,
leftEars,
rightEars,
leftIndex,
rightIndex,
leftFinger,
rightFinger
FROM gamedata_actor_templates
INNER JOIN gamedata_actor_appearance ON gamedata_actor_templates.id = gamedata_actor_appearance.id
WHERE gamedata_actor_templates.id = @templateId
";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@templateId", id);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
//Handle Name
if (reader.IsDBNull(1))
displayNameId = reader.GetUInt32(0);
else
{
customDisplayName = reader.GetString(1);
displayNameId = 0xFFFFFFF;
}
//Handle Appearance
modelId = reader.GetUInt32(2);
appearanceIds[Character.SIZE] = reader.GetUInt32(3);
appearanceIds[Character.COLORINFO] = (uint)(reader.GetUInt32(18) | (reader.GetUInt32(17) << 10) | (reader.GetUInt32(19) << 20)); //17 - Skin Color, 16 - Hair Color, 18 - Eye Color
appearanceIds[Character.FACEINFO] = PrimitiveConversion.ToUInt32(CharacterUtils.getFaceInfo(reader.GetByte(8), reader.GetByte(9), reader.GetByte(7), reader.GetByte(16), reader.GetByte(15), reader.GetByte(14), reader.GetByte(13), reader.GetByte(12), reader.GetByte(11), reader.GetByte(10)));
appearanceIds[Character.HIGHLIGHT_HAIR] = (uint)(reader.GetUInt32(5) | reader.GetUInt32(4) << 10); //5- Hair Highlight, 4 - Hair Style
appearanceIds[Character.VOICE] = reader.GetUInt32(19);
appearanceIds[Character.WEAPON1] = reader.GetUInt32(21);
//appearanceIds[Character.WEAPON2] = reader.GetUInt32(22);
appearanceIds[Character.HEADGEAR] = reader.GetUInt32(28);
appearanceIds[Character.BODYGEAR] = reader.GetUInt32(29);
appearanceIds[Character.LEGSGEAR] = reader.GetUInt32(30);
appearanceIds[Character.HANDSGEAR] = reader.GetUInt32(31);
appearanceIds[Character.FEETGEAR] = reader.GetUInt32(32);
appearanceIds[Character.WAISTGEAR] = reader.GetUInt32(33);
appearanceIds[Character.R_EAR] = reader.GetUInt32(34);
appearanceIds[Character.L_EAR] = reader.GetUInt32(35);
appearanceIds[Character.R_FINGER] = reader.GetUInt32(38);
appearanceIds[Character.L_FINGER] = reader.GetUInt32(39);
}
}
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Dispose();
}
}
}
public void queuePacket(BasePacket packet)
{
playerSession.queuePacket(packet);
@ -713,6 +716,94 @@ namespace FFXIVClassic_Map_Server.Actors
//zone.broadcastPacketAroundActor(this, worldMasterMessage);
}
public void addItem(uint itemId, ushort type, int quantity, byte quality)
{
List<SubPacket> addItemPackets = new List<SubPacket>();
Item storedItem = null;
//Check if item id exists
switch (type)
{
case InventorySetBeginPacket.CODE_INVENTORY:
foreach (Item item in invNormal)
{
if (item.itemId == itemId)
{
storedItem = item;
break;
}
}
break;
case InventorySetBeginPacket.CODE_KEYITEMS:
break;
case InventorySetBeginPacket.CODE_CURRANCY:
break;
case InventorySetBeginPacket.CODE_MELDREQUEST:
break;
case InventorySetBeginPacket.CODE_BAZAAR:
break;
case InventorySetBeginPacket.CODE_LOOT:
break;
}
//Update lists and db
queuePacket(InventoryBeginChangePacket.buildPacket(actorId));
switch (type)
{
case InventorySetBeginPacket.CODE_INVENTORY:
queuePacket(InventorySetBeginPacket.buildPacket(actorId, 200, InventorySetBeginPacket.CODE_INVENTORY));
if (storedItem == null)
{
Item addedItem = Database.addItem(this, itemId, quantity, quality, false, 100, type);
invNormal.Add(addedItem);
sendInventoryPackets(addedItem);
}
else
{
Database.addQuantity(this, itemId, quantity);
storedItem.quantity += quantity;
sendInventoryPackets(storedItem);
}
queuePacket(InventorySetEndPacket.buildPacket(actorId));
break;
case InventorySetBeginPacket.CODE_KEYITEMS:
break;
case InventorySetBeginPacket.CODE_CURRANCY:
break;
case InventorySetBeginPacket.CODE_MELDREQUEST:
break;
case InventorySetBeginPacket.CODE_BAZAAR:
break;
case InventorySetBeginPacket.CODE_LOOT:
break;
}
//addItemPackets.Add(InventorySetBeginPacket.buildPacket(actorId, MAXSIZE_INVENTORY_NORMAL, type));
//sendInventoryPackets()
queuePacket(InventorySetEndPacket.buildPacket(actorId));
}
public void removeItem(uint itemId, uint quantity)
{
}
public void changeDurability(uint slot, uint durabilityChange)
{
}
public void changeSpiritBind(uint slot, uint spiritBindChange)
{
}
public void changeMateria(uint slot, byte materiaSlot, byte materiaId)
{
}
public void runEventFunction(string functionName, params object[] parameters)
{
List<LuaParam> lParams = LuaUtils.createLuaParamList(parameters);
@ -741,8 +832,7 @@ namespace FFXIVClassic_Map_Server.Actors
return eventMenuId;
}
internal void sendInstanceUpdate()
public void sendInstanceUpdate()
{
//Update Instance
@ -754,5 +844,26 @@ namespace FFXIVClassic_Map_Server.Actors
}
}
public int getLastInventorySlot(ushort type)
{
switch (type)
{
case InventorySetBeginPacket.CODE_INVENTORY:
return invNormal.Count == 0 ? 0 : invNormal.Count() + 1;
case InventorySetBeginPacket.CODE_KEYITEMS:
return invKeyItems.Count == 0 ? 0 : invKeyItems.Count() + 1;
case InventorySetBeginPacket.CODE_CURRANCY:
return invCurrancy.Count == 0 ? 0 : invCurrancy.Count() + 1;
case InventorySetBeginPacket.CODE_MELDREQUEST:
return invMeldRequest.Count == 0 ? 0 : invMeldRequest.Count() + 1;
case InventorySetBeginPacket.CODE_BAZAAR:
return invBazaar.Count == 0 ? 0 : invBazaar.Count() + 1;
case InventorySetBeginPacket.CODE_LOOT:
return invLoot.Count == 0 ? 0 : invLoot.Count() + 1;
}
return 0;
}
}
}

View File

@ -15,7 +15,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
public uint slot;
public bool isUntradeable = false;
public bool isHighQuality = false;
public byte quality = 1;
public uint durability = 0;
public ushort spiritbind = 0;
@ -35,6 +35,23 @@ namespace FFXIVClassic_Map_Server.dataobjects
this.slot = slot;
}
public Item(uint uniqueId, uint itemId, int quantity, uint slot, bool isUntradeable, byte qualityNumber, uint durability, ushort spiritbind, byte materia1, byte materia2, byte materia3, byte materia4, byte materia5)
{
this.uniqueId = uniqueId;
this.itemId = itemId;
this.quantity = quantity;
this.slot = slot;
this.isUntradeable = isUntradeable;
this.quality = qualityNumber;
this.durability = durability;
this.spiritbind = spiritbind;
this.materia1 = materia1;
this.materia2 = materia2;
this.materia3 = materia3;
this.materia4 = materia4;
this.materia5 = materia5;
}
public byte[] toPacketBytes()
{
byte[] data = new byte[0x70];
@ -57,7 +74,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
binWriter.Write((UInt32)0x00000000);
binWriter.Write(isHighQuality ? (byte)0x02 : (byte)0x01);
binWriter.Write((byte)quality);
binWriter.Write((byte)0x01);
binWriter.Write((uint)durability);

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class EquipmentChangePacket
class EquipmentListX01Packet
{
public const ushort OPCODE = 0x014D;
public const uint PACKET_SIZE = 0x28;

View File

@ -8,9 +8,9 @@ using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class EquipmentSetupPacket
class EquipmentListX08Packet
{
public const ushort OPCODE = 0x014E;
public const ushort OPCODE = 0x14E;
public const uint PACKET_SIZE = 0x58;
public const uint UNEQUIPPED = 0xFFFFFFFF;
@ -36,7 +36,7 @@ namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
private uint[] equipment = new uint[0x17];
public EquipmentSetupPacket()
public EquipmentListX08Packet()
{
for (int i = 0; i < equipment.Length; i++)
equipment[i] = UNEQUIPPED; //We will use this as "Unequipped"

View File

@ -0,0 +1,98 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class EquipmentListX16Packet
{
public const ushort OPCODE = 0x14F;
public const uint PACKET_SIZE = 0x80;
public const uint UNEQUIPPED = 0xFFFFFFFF;
public const int SLOT_MAINHAND = 0x00;
public const int SLOT_OFFHAND = 0x01;
public const int SLOT_THROWINGWEAPON = 0x04;
public const int SLOT_PACK = 0x05;
public const int SLOT_POUCH = 0x06;
public const int SLOT_HEAD = 0x08;
public const int SLOT_UNDERSHIRT = 0x09;
public const int SLOT_BODY = 0x0A;
public const int SLOT_UNDERGARMENT = 0x0B;
public const int SLOT_LEGS = 0x0C;
public const int SLOT_HANDS = 0x0D;
public const int SLOT_BOOTS = 0x0E;
public const int SLOT_WAIST = 0x0F;
public const int SLOT_NECK = 0x10;
public const int SLOT_EARS = 0x11;
public const int SLOT_WRISTS = 0x13;
public const int SLOT_RIGHTFINGER = 0x15;
public const int SLOT_LEFTFINGER = 0x16;
private uint[] equipment = new uint[0x17];
public EquipmentListX16Packet()
{
for (int i = 0; i < equipment.Length; i++)
equipment[i] = UNEQUIPPED; //We will use this as "Unequipped"
}
public void setItem(int slot, uint itemSlot)
{
if (slot >= equipment.Length)
return;
equipment[slot] = itemSlot;
}
public List<SubPacket> buildPackets(uint playerActorID)
{
List<SubPacket> packets = new List<SubPacket>();
int packetCount = 0;
int runningCount = 0;
byte[] data = new byte[PACKET_SIZE - 0x20];
MemoryStream mem = new MemoryStream(data);
BinaryWriter binWriter = new BinaryWriter(mem);
for (int i = 0; i < equipment.Length; i++)
{
if (equipment[i] == UNEQUIPPED)
continue;
binWriter.Write((UInt16)i);
binWriter.Write((UInt32)equipment[i]);
packetCount++;
runningCount++;
//Create another packet
if (runningCount >= 16)
{
packetCount = 0;
binWriter.Write((UInt32)8);
binWriter.Dispose();
mem.Dispose();
packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data));
data = new byte[PACKET_SIZE - 0x20];
mem = new MemoryStream(data);
binWriter = new BinaryWriter(mem);
}
}
//Create any leftover subpacket
binWriter.BaseStream.Seek(0x30, SeekOrigin.Begin);
binWriter.Write((UInt32)packetCount);
binWriter.Dispose();
mem.Dispose();
packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data));
return packets;
}
}
}

View File

@ -0,0 +1,98 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class EquipmentListX32Packet
{
public const ushort OPCODE = 0x150;
public const uint PACKET_SIZE = 0xE0;
public const uint UNEQUIPPED = 0xFFFFFFFF;
public const int SLOT_MAINHAND = 0x00;
public const int SLOT_OFFHAND = 0x01;
public const int SLOT_THROWINGWEAPON = 0x04;
public const int SLOT_PACK = 0x05;
public const int SLOT_POUCH = 0x06;
public const int SLOT_HEAD = 0x08;
public const int SLOT_UNDERSHIRT = 0x09;
public const int SLOT_BODY = 0x0A;
public const int SLOT_UNDERGARMENT = 0x0B;
public const int SLOT_LEGS = 0x0C;
public const int SLOT_HANDS = 0x0D;
public const int SLOT_BOOTS = 0x0E;
public const int SLOT_WAIST = 0x0F;
public const int SLOT_NECK = 0x10;
public const int SLOT_EARS = 0x11;
public const int SLOT_WRISTS = 0x13;
public const int SLOT_RIGHTFINGER = 0x15;
public const int SLOT_LEFTFINGER = 0x16;
private uint[] equipment = new uint[0x17];
public EquipmentListX32Packet()
{
for (int i = 0; i < equipment.Length; i++)
equipment[i] = UNEQUIPPED; //We will use this as "Unequipped"
}
public void setItem(int slot, uint itemSlot)
{
if (slot >= equipment.Length)
return;
equipment[slot] = itemSlot;
}
public List<SubPacket> buildPackets(uint playerActorID)
{
List<SubPacket> packets = new List<SubPacket>();
int packetCount = 0;
int runningCount = 0;
byte[] data = new byte[PACKET_SIZE - 0x20];
MemoryStream mem = new MemoryStream(data);
BinaryWriter binWriter = new BinaryWriter(mem);
for (int i = 0; i < equipment.Length; i++)
{
if (equipment[i] == UNEQUIPPED)
continue;
binWriter.Write((UInt16)i);
binWriter.Write((UInt32)equipment[i]);
packetCount++;
runningCount++;
//Create another packet
if (runningCount >= 32)
{
packetCount = 0;
binWriter.Write((UInt32)8);
binWriter.Dispose();
mem.Dispose();
packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data));
data = new byte[PACKET_SIZE - 0x20];
mem = new MemoryStream(data);
binWriter = new BinaryWriter(mem);
}
}
//Create any leftover subpacket
binWriter.BaseStream.Seek(0x30, SeekOrigin.Begin);
binWriter.Write((UInt32)packetCount);
binWriter.Dispose();
mem.Dispose();
packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data));
return packets;
}
}
}

View File

@ -0,0 +1,98 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class EquipmentListX64Packet
{
public const ushort OPCODE = 0x151;
public const uint PACKET_SIZE = 0x194;
public const uint UNEQUIPPED = 0xFFFFFFFF;
public const int SLOT_MAINHAND = 0x00;
public const int SLOT_OFFHAND = 0x01;
public const int SLOT_THROWINGWEAPON = 0x04;
public const int SLOT_PACK = 0x05;
public const int SLOT_POUCH = 0x06;
public const int SLOT_HEAD = 0x08;
public const int SLOT_UNDERSHIRT = 0x09;
public const int SLOT_BODY = 0x0A;
public const int SLOT_UNDERGARMENT = 0x0B;
public const int SLOT_LEGS = 0x0C;
public const int SLOT_HANDS = 0x0D;
public const int SLOT_BOOTS = 0x0E;
public const int SLOT_WAIST = 0x0F;
public const int SLOT_NECK = 0x10;
public const int SLOT_EARS = 0x11;
public const int SLOT_WRISTS = 0x13;
public const int SLOT_RIGHTFINGER = 0x15;
public const int SLOT_LEFTFINGER = 0x16;
private uint[] equipment = new uint[0x17];
public EquipmentListX64Packet()
{
for (int i = 0; i < equipment.Length; i++)
equipment[i] = UNEQUIPPED; //We will use this as "Unequipped"
}
public void setItem(int slot, uint itemSlot)
{
if (slot >= equipment.Length)
return;
equipment[slot] = itemSlot;
}
public List<SubPacket> buildPackets(uint playerActorID)
{
List<SubPacket> packets = new List<SubPacket>();
int packetCount = 0;
int runningCount = 0;
byte[] data = new byte[PACKET_SIZE - 0x20];
MemoryStream mem = new MemoryStream(data);
BinaryWriter binWriter = new BinaryWriter(mem);
for (int i = 0; i < equipment.Length; i++)
{
if (equipment[i] == UNEQUIPPED)
continue;
binWriter.Write((UInt16)i);
binWriter.Write((UInt32)equipment[i]);
packetCount++;
runningCount++;
//Create another packet
if (runningCount >= 64)
{
packetCount = 0;
binWriter.Write((UInt32)8);
binWriter.Dispose();
mem.Dispose();
packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data));
data = new byte[PACKET_SIZE - 0x20];
mem = new MemoryStream(data);
binWriter = new BinaryWriter(mem);
}
}
//Create any leftover subpacket
binWriter.BaseStream.Seek(0x30, SeekOrigin.Begin);
binWriter.Write((UInt32)packetCount);
binWriter.Dispose();
mem.Dispose();
packets.Add(new SubPacket(OPCODE, playerActorID, playerActorID, data));
return packets;
}
}
}

View File

@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
class InventoryItemPacket
{
public const ushort OPCODE = 0x014B;
public const ushort OPCODE = 0x014A;
public const uint PACKET_SIZE = 0x90;
public static SubPacket buildPacket(uint playerActorID, List<Item> items, ref int listOffset)

View File

@ -0,0 +1,33 @@
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{
class InventoryListX01Packet
{
public const ushort OPCODE = 0x0148;
public const uint PACKET_SIZE = 0x90;
public static SubPacket buildPacket(uint playerActorID, Item item)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write(item.toPacketBytes());
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,45 @@
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{
class InventoryListX08Packet
{
public const ushort OPCODE = 0x0149;
public const uint PACKET_SIZE = 0x3A8;
public static SubPacket buildPacket(uint playerActorID, List<Item> items, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (items.Count - listOffset <= 8)
max = items.Count - listOffset;
else
max = 8;
for (int i = listOffset; i < max; i++)
{
binWriter.Write(items[i].toPacketBytes());
listOffset++;
}
binWriter.Seek(0x380, SeekOrigin.Begin);
binWriter.Write((UInt32)max);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,42 @@
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{
class InventoryListX16Packet
{
public const ushort OPCODE = 0x014A;
public const uint PACKET_SIZE = 0x720;
public static SubPacket buildPacket(uint playerActorID, List<Item> items, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (items.Count - listOffset <= 16)
max = items.Count - listOffset;
else
max = 16;
for (int i = listOffset; i < items.Count; i++)
{
binWriter.Write(items[i].toPacketBytes());
listOffset++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,42 @@
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{
class InventoryListX32Packet
{
public const ushort OPCODE = 0x014B;
public const uint PACKET_SIZE = 0xE20;
public static SubPacket buildPacket(uint playerActorID, List<Item> items, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (items.Count - listOffset <= 32)
max = items.Count - listOffset;
else
max = 32;
for (int i = listOffset; i < items.Count; i++)
{
binWriter.Write(items[i].toPacketBytes());
listOffset++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,42 @@
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{
class InventoryListX64Packet
{
public const ushort OPCODE = 0x014C;
public const uint PACKET_SIZE = 0x1C20;
public static SubPacket buildPacket(uint playerActorID, List<Item> items, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (items.Count - listOffset <= 64)
max = items.Count - listOffset;
else
max = 64;
for (int i = listOffset; i < max; i++)
{
binWriter.Write(items[i].toPacketBytes());
listOffset++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,31 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class InventoryRemoveX01Packet
{
public const ushort OPCODE = 0x0152;
public const uint PACKET_SIZE = 0x28;
public static SubPacket buildPacket(uint playerActorID, ushort slot)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt16)slot);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,44 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class InventoryRemoveX08Packet
{
public const ushort OPCODE = 0x0153;
public const uint PACKET_SIZE = 0x38;
public static SubPacket buildPacket(uint playerActorID, List<ushort> slots, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (slots.Count - listOffset <= 8)
max = slots.Count - listOffset;
else
max = 8;
for (int i = listOffset; i < max; i++)
{
binWriter.Write((UInt16)slots[i]);
listOffset++;
}
binWriter.Seek(0x10, SeekOrigin.Begin);
binWriter.Write((Byte)max);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,41 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class InventoryRemoveX16Packet
{
public const ushort OPCODE = 0x154;
public const uint PACKET_SIZE = 0x40;
public static SubPacket buildPacket(uint playerActorID, List<ushort> slots, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (slots.Count - listOffset <= 16)
max = slots.Count - listOffset;
else
max = 16;
for (int i = listOffset; i < 16; i++)
{
binWriter.Write((UInt16)slots[i]);
listOffset++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,41 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class InventoryRemoveX32Packet
{
public const ushort OPCODE = 0x0155;
public const uint PACKET_SIZE = 0x60;
public static SubPacket buildPacket(uint playerActorID, List<ushort> slots, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (slots.Count - listOffset <= 32)
max = slots.Count - listOffset;
else
max = 32;
for (int i = listOffset; i < max; i++)
{
binWriter.Write((UInt16)slots[i]);
listOffset++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -0,0 +1,41 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
{
class InventoryRemoveX64Packet
{
public const ushort OPCODE = 0x156;
public const uint PACKET_SIZE = 0xA0;
public static SubPacket buildPacket(uint playerActorID, List<ushort> slots, ref int listOffset)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
int max;
if (slots.Count - listOffset <= 64)
max = slots.Count - listOffset;
else
max = 64;
for (int i = listOffset; i < max; i++)
{
binWriter.Write((UInt16)slots[i]);
listOffset++;
}
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View File

@ -13,10 +13,13 @@ namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
public const ushort OPCODE = 0x0146;
public const uint PACKET_SIZE = 0x28;
public const ushort CODE_ITEMS = 0x0000;
public const ushort CODE_CURRANCYITEMS = 0x0063;
public const ushort CODE_KEYITEMS = 0x0064;
public const ushort CODE_EQUIPMENT = 0x00FE;
public const ushort CODE_INVENTORY = 0x0000; //Max 0xC8
public const ushort CODE_LOOT = 0x0004; //Max 0xA
public const ushort CODE_MELDREQUEST = 0x0005; //Max 0x04
public const ushort CODE_BAZAAR = 0x0007; //Max 0x0A
public const ushort CODE_CURRANCY = 0x0063; //Max 0x140
public const ushort CODE_KEYITEMS = 0x0064; //Max 0x500
public const ushort CODE_EQUIPMENT = 0x00FE; //Max 0x23
public static SubPacket buildPacket(uint playerActorID, ushort size, ushort code)
{