diff --git a/FFXIVClassic Map Server/ClientConnection.cs b/FFXIVClassic Map Server/ClientConnection.cs index 3d80990b..e00b073e 100644 --- a/FFXIVClassic Map Server/ClientConnection.cs +++ b/FFXIVClassic Map Server/ClientConnection.cs @@ -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 sendPacketQueue = new BlockingCollection(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 { diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 2547dfdf..530d0a8d 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -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 getInventory(Player player, uint slotOffset, uint type) + { + List items = new List(); + + 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); } diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index a590db7b..9c8bf883 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -125,6 +125,7 @@ + @@ -135,17 +136,30 @@ + + + + + + + + + + + + + - + - + diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index 7ed19a98..17710ea2 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -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 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 diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 58236d45..6d73e3b2 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -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; @@ -44,13 +52,22 @@ namespace FFXIVClassic_Map_Server.Actors public const int TIMER_BEHEST = 16; public const int TIMER_COMPANYBEHEST = 17; public const int TIMER_RETURN = 18; - public const int TIMER_SKIRMISH = 19; + public const int TIMER_SKIRMISH = 19; + //Player Info public uint[] timers = new uint[20]; - public ushort currentJob; public uint currentTitle; + //Inventory + public List invNormal = new List(); + public List invCurrancy = new List(); + public List invKeyItems = new List(); + public List invLoot = new List(); + public List invMeldRequest = new List(); + public List invBazaar = new List(); + 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 items = new List(); - 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 packets = new List(); + packets.Add(InventorySetBeginPacket.buildPacket(actorId, 200, InventorySetBeginPacket.CODE_INVENTORY)); + packets.Add(InventoryListX08Packet.buildPacket(actorId, items,ref count)); + packets.Add(InventorySetEndPacket.buildPacket(actorId)); - List setinvPackets = new List(); - 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,116 +520,87 @@ namespace FFXIVClassic_Map_Server.Actors } + private void sendInventoryPackets(Item item) + { + queuePacket(InventoryListX01Packet.buildPacket(actorId, item)); + } + + private void sendInventoryPackets(List 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 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 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) @@ -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 addItemPackets = new List(); + 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 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; + } } } diff --git a/FFXIVClassic Map Server/dataobjects/Item.cs b/FFXIVClassic Map Server/dataobjects/Item.cs index 5a121c5b..fb088c11 100644 --- a/FFXIVClassic Map Server/dataobjects/Item.cs +++ b/FFXIVClassic Map Server/dataobjects/Item.cs @@ -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); diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentChangePacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX01Packet.cs similarity index 96% rename from FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentChangePacket.cs rename to FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX01Packet.cs index 6208cef0..ec40f23a 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentChangePacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX01Packet.cs @@ -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; diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentSetupPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX08Packet.cs similarity index 96% rename from FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentSetupPacket.cs rename to FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX08Packet.cs index 4d8cc3de..81b0c635 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentSetupPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX08Packet.cs @@ -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" diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX16Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX16Packet.cs new file mode 100644 index 00000000..40d254e0 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX16Packet.cs @@ -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 buildPackets(uint playerActorID) + { + List packets = new List(); + 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; + } + + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX32Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX32Packet.cs new file mode 100644 index 00000000..81350a15 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX32Packet.cs @@ -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 buildPackets(uint playerActorID) + { + List packets = new List(); + 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; + } + + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX64Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX64Packet.cs new file mode 100644 index 00000000..ed1e8b2e --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/EquipmentListX64Packet.cs @@ -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 buildPackets(uint playerActorID) + { + List packets = new List(); + 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; + } + + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryItemPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryItemPacket.cs index 6170119e..b8d7af78 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryItemPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryItemPacket.cs @@ -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 items, ref int listOffset) diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX01Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX01Packet.cs new file mode 100644 index 00000000..a20e1879 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX01Packet.cs @@ -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); + } + + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX08Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX08Packet.cs new file mode 100644 index 00000000..a2093215 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX08Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX16Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX16Packet.cs new file mode 100644 index 00000000..1d73b514 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX16Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX32Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX32Packet.cs new file mode 100644 index 00000000..b19461e7 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX32Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX64Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX64Packet.cs new file mode 100644 index 00000000..c74a7e4c --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryListX64Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX01Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX01Packet.cs new file mode 100644 index 00000000..b91c56fb --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX01Packet.cs @@ -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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX08Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX08Packet.cs new file mode 100644 index 00000000..79f805c5 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX08Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX16Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX16Packet.cs new file mode 100644 index 00000000..30ed3d08 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX16Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX32Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX32Packet.cs new file mode 100644 index 00000000..c7b8b59d --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX32Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX64Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX64Packet.cs new file mode 100644 index 00000000..632b2e36 --- /dev/null +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventoryRemoveX64Packet.cs @@ -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 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); + } + } +} diff --git a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs index 0327af2e..6c0d6881 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/inventory/InventorySetBeginPacket.cs @@ -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) {