From 235a5adae3d86f542096d70fa038d4b3f9743d47 Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Wed, 14 Oct 2015 23:48:49 -0400 Subject: [PATCH] Fixed bugs on how subpackets handled. Reorganized subpackets and split header with game header. --- FFXIVClassic Map Server/PacketProcessor.cs | 446 +++++++++--------- FFXIVClassic Map Server/packets/SubPacket.cs | 71 ++- .../packets/send/login/InitPacket.cs | 2 +- 3 files changed, 286 insertions(+), 233 deletions(-) diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index e5cb10dd..1c71ebe9 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -89,268 +89,276 @@ namespace FFXIVClassic_Lobby_Server if (packet.header.isEncrypted == 0x01) BasePacket.decryptPacket(client.blowfish, ref packet); + packet.debugPrintPacket(); List subPackets = packet.getSubpackets(); foreach (SubPacket subpacket in subPackets) { - //Console.WriteLine(client.getAddress()); - switch (subpacket.header.opcode) - { - //Initial - case 0x0000: - BasePacket init = InitPacket.buildPacket(0, Utils.UnixTimeStampUTC()); - BasePacket reply2 = new BasePacket("./packets/login/login2.bin"); - - //Already Handshaked - if (client.owner != 0) - { - using (MemoryStream mem = new MemoryStream(reply2.data)) - { - using (BinaryWriter binReader = new BinaryWriter(mem)) - { - binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); - binReader.Write(player.actorID); - } - } - - client.queuePacket(init); - client.queuePacket(reply2); - break; - } - - uint actorID = 0; - using (MemoryStream mem = new MemoryStream(packet.data)) - { - using (BinaryReader binReader = new BinaryReader(mem)) - { - try - { - byte[] readIn = new byte[12]; - binReader.BaseStream.Seek(0x14, SeekOrigin.Begin); - binReader.Read(readIn, 0, 12); - actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn)); - } - catch (Exception) - {} - } - } - - if (actorID == 0) - break; - - //Second connection - if (mPlayers.ContainsKey(actorID)) - player = mPlayers[actorID]; + if (subpacket.header.type == 0x01) + { + BasePacket init = InitPacket.buildPacket(0, Utils.UnixTimeStampUTC()); + BasePacket reply2 = new BasePacket("./packets/login/login2.bin"); + //Already Handshaked + if (client.owner != 0) + { using (MemoryStream mem = new MemoryStream(reply2.data)) { using (BinaryWriter binReader = new BinaryWriter(mem)) { binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); - binReader.Write(actorID); + binReader.Write(player.actorID); } } - Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); - - if (player == null) - { - player = new Player(actorID); - mPlayers[actorID] = player; - client.owner = actorID; - client.connType = 0; - player.setConnection1(client); - } - else - { - client.owner = actorID; - client.connType = 1; - player.setConnection2(client); - } - - //Get Character info - //Create player actor client.queuePacket(init); client.queuePacket(reply2); break; - //Ping - case 0x0001: - //subpacket.debugPrintSubPacket(); - PingPacket pingPacket = new PingPacket(subpacket.data); - client.queuePacket(BasePacket.createPacket(PongPacket.buildPacket(player.actorID, pingPacket.time), true, false)); + } + + uint actorID = 0; + using (MemoryStream mem = new MemoryStream(packet.data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try + { + byte[] readIn = new byte[12]; + binReader.BaseStream.Seek(0x14, SeekOrigin.Begin); + binReader.Read(readIn, 0, 12); + actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn)); + } + catch (Exception) + { } + } + } + + if (actorID == 0) break; - //Unknown - case 0x0002: - subpacket.debugPrintSubPacket(); - - BasePacket reply5 = new BasePacket("./packets/login/login5.bin"); - BasePacket reply6 = new BasePacket("./packets/login/login6_data.bin"); - BasePacket reply7 = new BasePacket("./packets/login/login7_data.bin"); - BasePacket reply8 = new BasePacket("./packets/login/login8_data.bin"); - BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); - BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); - BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); - BasePacket reply12 = new BasePacket("./packets/login/login12.bin"); - BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); - BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); + //Second connection + if (mPlayers.ContainsKey(actorID)) + player = mPlayers[actorID]; -#region replaceid - currancy.replaceActorID(player.actorID); - keyitems.replaceActorID(player.actorID); + using (MemoryStream mem = new MemoryStream(reply2.data)) + { + using (BinaryWriter binReader = new BinaryWriter(mem)) + { + binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); + binReader.Write(actorID); + } + } - reply5.replaceActorID(player.actorID); - reply6.replaceActorID(player.actorID); - reply7.replaceActorID(player.actorID); - reply8.replaceActorID(player.actorID); - reply9.replaceActorID(player.actorID); - reply10.replaceActorID(player.actorID); - reply11.replaceActorID(player.actorID); - reply12.replaceActorID(player.actorID); -#endregion + Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); - client.queuePacket(BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false)); - client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false)); - client.queuePacket(BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false)); + if (player == null) + { + player = new Player(actorID); + mPlayers[actorID] = player; + client.owner = actorID; + client.connType = 0; + player.setConnection1(client); + } + else + { + client.owner = actorID; + client.connType = 1; + player.setConnection2(client); + } - client.queuePacket(reply5); + //Get Character info + //Create player actor + client.queuePacket(init); + client.queuePacket(reply2); + break; + } + else if (subpacket.header.type == 0x08) + { - client.queuePacket(BasePacket.createPacket(AddActorPacket.buildPacket(player.actorID, player.actorID, 0), true, false)); + } + else if (subpacket.header.type == 0x03) + { + switch (subpacket.gameMessage.opcode) + { + //Ping + case 0x0001: + //subpacket.debugPrintSubPacket(); + PingPacket pingPacket = new PingPacket(subpacket.data); + client.queuePacket(BasePacket.createPacket(PongPacket.buildPacket(player.actorID, pingPacket.time), true, false)); + break; + //Unknown + case 0x0002: + subpacket.debugPrintSubPacket(); - client.queuePacket(reply6); + BasePacket reply5 = new BasePacket("./packets/login/login5.bin"); + BasePacket reply6 = new BasePacket("./packets/login/login6_data.bin"); + BasePacket reply7 = new BasePacket("./packets/login/login7_data.bin"); + BasePacket reply8 = new BasePacket("./packets/login/login8_data.bin"); + BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); + BasePacket reply10 = new BasePacket("./packets/login/login10.bin"); + BasePacket reply11 = new BasePacket("./packets/login/login11.bin"); + BasePacket reply12 = new BasePacket("./packets/login/login12.bin"); - client.queuePacket(BasePacket.createPacket(SetActorPositionPacket.buildPacket(player.actorID, player.actorID, SetActorPositionPacket.INNPOS_X, SetActorPositionPacket.INNPOS_Y, SetActorPositionPacket.INNPOS_Z, SetActorPositionPacket.INNPOS_ROT, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE), true, false)); - client.queuePacket(BasePacket.createPacket(player.getActor().createSpeedPacket(player.actorID), true, false)); - client.queuePacket(BasePacket.createPacket(player.getActor().createStatePacket(player.actorID), true, false)); + BasePacket keyitems = new BasePacket("./packets/login/keyitems.bin"); + BasePacket currancy = new BasePacket("./packets/login/currancy.bin"); - client.queuePacket(BasePacket.createPacket(player.getActor().createNamePacket(player.actorID), true, false)); - client.queuePacket(BasePacket.createPacket(player.getActor().createAppearancePacket(player.actorID), true, false)); + #region replaceid + currancy.replaceActorID(player.actorID); + keyitems.replaceActorID(player.actorID); - ////////ITEMS//////// - client.queuePacket(BasePacket.createPacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false)); + reply5.replaceActorID(player.actorID); + reply6.replaceActorID(player.actorID); + reply7.replaceActorID(player.actorID); + reply8.replaceActorID(player.actorID); + reply9.replaceActorID(player.actorID); + reply10.replaceActorID(player.actorID); + reply11.replaceActorID(player.actorID); + reply12.replaceActorID(player.actorID); + #endregion -#region itemsetup + client.queuePacket(BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false)); + client.queuePacket(BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false)); + client.queuePacket(BasePacket.createPacket(SetMusicPacket.buildPacket(player.actorID, 0x3D, 0x01), true, false)); - //TEST - List items = new List(); - items.Add(new Item(1337, 8030920, 5)); //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 + client.queuePacket(reply5); - int count = 0; - - items[2].isHighQuality = true; - items[0].durability = 9999; - items[0].spiritbind = 10000; - items[0].materia1 = 6; - items[0].materia2 = 7; - items[0].materia3 = 8; - items[0].materia4 = 9; - items[0].materia5 = 10; - items[1].durability = 9999; - items[2].durability = 0xFFFFFFF; - items[3].durability = 9999; - items[4].quantity = 99; + client.queuePacket(BasePacket.createPacket(AddActorPacket.buildPacket(player.actorID, player.actorID, 0), true, false)); - //Reused - SubPacket endInventory = InventorySetEndPacket.buildPacket(player.actorID); - SubPacket beginInventory = InventorySetBeginPacket.buildPacket(player.actorID, 200, 00); - SubPacket setInventory = InventoryItemPacket.buildPacket(player.actorID, items, ref count); + client.queuePacket(reply6); - List setinvPackets = new List(); - setinvPackets.Add(beginInventory); - setinvPackets.Add(setInventory); - setinvPackets.Add(endInventory); -#endregion + client.queuePacket(BasePacket.createPacket(SetActorPositionPacket.buildPacket(player.actorID, player.actorID, SetActorPositionPacket.INNPOS_X, SetActorPositionPacket.INNPOS_Y, SetActorPositionPacket.INNPOS_Z, SetActorPositionPacket.INNPOS_ROT, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE), true, false)); + client.queuePacket(BasePacket.createPacket(player.getActor().createSpeedPacket(player.actorID), true, false)); + client.queuePacket(BasePacket.createPacket(player.getActor().createStatePacket(player.actorID), true, false)); - client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); - - //client.queuePacket(currancy); - //client.queuePacket(keyitems); + client.queuePacket(BasePacket.createPacket(player.getActor().createNamePacket(player.actorID), true, false)); + client.queuePacket(BasePacket.createPacket(player.getActor().createAppearancePacket(player.actorID), true, false)); -#region equipsetup - 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); -#endregion + ////////ITEMS//////// + client.queuePacket(BasePacket.createPacket(InventoryBeginChangePacket.buildPacket(player.actorID), true, false)); - //Equip Init - client.queuePacket(BasePacket.createPacket(InventorySetBeginPacket.buildPacket(player.actorID, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false)); - client.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(player.actorID), true, false)); - client.queuePacket(BasePacket.createPacket(InventorySetEndPacket.buildPacket(player.actorID), true, false)); + #region itemsetup - client.queuePacket(BasePacket.createPacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false)); - ////////ITEMS//////// + //TEST + List items = new List(); + items.Add(new Item(1337, 8030920, 5)); //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 - //The rest of hardcode - client.queuePacket(reply7); - client.queuePacket(reply8); - client.queuePacket(reply9); - client.queuePacket(reply10); - //client.queuePacket(reply11); - client.queuePacket(reply12); + int count = 0; - inn.addActorToZone(player.getActor()); + items[2].isHighQuality = true; + items[0].durability = 9999; + items[0].spiritbind = 10000; + items[0].materia1 = 6; + items[0].materia2 = 7; + items[0].materia3 = 8; + items[0].materia4 = 9; + items[0].materia5 = 10; + items[1].durability = 9999; + items[2].durability = 0xFFFFFFF; + items[3].durability = 9999; + items[4].quantity = 99; - break; - //Chat Received - case 0x0003: - subpacket.debugPrintSubPacket(); - break; - //Update Position - case 0x00CA: + //Reused + SubPacket endInventory = InventorySetEndPacket.buildPacket(player.actorID); + SubPacket beginInventory = InventorySetBeginPacket.buildPacket(player.actorID, 200, 00); + SubPacket setInventory = InventoryItemPacket.buildPacket(player.actorID, items, ref count); + + List setinvPackets = new List(); + setinvPackets.Add(beginInventory); + setinvPackets.Add(setInventory); + setinvPackets.Add(endInventory); + #endregion + + client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); + + //client.queuePacket(currancy); + //client.queuePacket(keyitems); + + #region equipsetup + 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); + #endregion + + //Equip Init + client.queuePacket(BasePacket.createPacket(InventorySetBeginPacket.buildPacket(player.actorID, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false)); + client.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(player.actorID), true, false)); + client.queuePacket(BasePacket.createPacket(InventorySetEndPacket.buildPacket(player.actorID), true, false)); + + client.queuePacket(BasePacket.createPacket(InventoryEndChangePacket.buildPacket(player.actorID), true, false)); + ////////ITEMS//////// + + //The rest of hardcode + client.queuePacket(reply7); + client.queuePacket(reply8); + client.queuePacket(reply9); + client.queuePacket(reply10); + //client.queuePacket(reply11); + client.queuePacket(reply12); + + inn.addActorToZone(player.getActor()); + + break; + //Chat Received + case 0x0003: + subpacket.debugPrintSubPacket(); + break; //Update Position - UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); - player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); + case 0x00CA: + //Update Position + UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); + player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); - //Update Instance - List instanceUpdatePackets = player.updateInstance(inn.getActorsAroundActor(player.getActor(), 50)); - foreach (BasePacket bp in instanceUpdatePackets) - client.queuePacket(bp); + //Update Instance + List instanceUpdatePackets = player.updateInstance(inn.getActorsAroundActor(player.getActor(), 50)); + foreach (BasePacket bp in instanceUpdatePackets) + client.queuePacket(bp); - break; - //Set Target - case 0x00CD: - subpacket.debugPrintSubPacket(); + break; + //Set Target + case 0x00CD: + subpacket.debugPrintSubPacket(); - SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); - player.getActor().currentTarget = setTarget.actorID; - client.queuePacket(BasePacket.createPacket(SetActorTargetAnimatedPacket.buildPacket(player.actorID, player.actorID, setTarget.actorID), true, false)); - break; - //Lock Target - case 0x00CC: - LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); - player.getActor().currentLockedTarget = lockTarget.actorID; - break; - //Start Script - case 0x012D: - subpacket.debugPrintSubPacket(); - //StartScriptPacket startScript = new StartScriptPacket(subpacket.data); - //client.queuePacket(new BasePacket("./packets/script/bed.bin")); - client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getActor().currentTarget, 137), true, false)); - break; - //Script Result - case 0x012E: - subpacket.debugPrintSubPacket(); - processScriptResult(subpacket); - break; - case 0x012F: - subpacket.debugPrintSubPacket(); - - break; - default: - Log.debug(String.Format("Unknown command 0x{0:X} received.", subpacket.header.opcode)); - subpacket.debugPrintSubPacket(); - break; + SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); + player.getActor().currentTarget = setTarget.actorID; + client.queuePacket(BasePacket.createPacket(SetActorTargetAnimatedPacket.buildPacket(player.actorID, player.actorID, setTarget.actorID), true, false)); + break; + //Lock Target + case 0x00CC: + LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); + player.getActor().currentLockedTarget = lockTarget.actorID; + break; + //Start Script + case 0x012D: + subpacket.debugPrintSubPacket(); + //StartScriptPacket startScript = new StartScriptPacket(subpacket.data); + //client.queuePacket(new BasePacket("./packets/script/bed.bin")); + client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getActor().currentTarget, 137), true, false)); + break; + //Script Result + case 0x012E: + subpacket.debugPrintSubPacket(); + processScriptResult(subpacket); + break; + case 0x012F: + subpacket.debugPrintSubPacket(); + + break; + default: + Log.debug(String.Format("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode)); + subpacket.debugPrintSubPacket(); + break; + } } } } diff --git a/FFXIVClassic Map Server/packets/SubPacket.cs b/FFXIVClassic Map Server/packets/SubPacket.cs index b443ce91..40ff4094 100644 --- a/FFXIVClassic Map Server/packets/SubPacket.cs +++ b/FFXIVClassic Map Server/packets/SubPacket.cs @@ -13,10 +13,15 @@ namespace FFXIVClassic_Lobby_Server.packets public struct SubPacketHeader { public ushort subpacketSize; - public ushort unknown0; //Always 0x03 + public ushort type; public uint sourceId; public uint targetId; public uint unknown1; + } + + [StructLayout(LayoutKind.Sequential)] + public struct GameMessageHeader + { public ushort unknown4; //Always 0x14 public ushort opcode; public uint unknown5; @@ -26,9 +31,11 @@ namespace FFXIVClassic_Lobby_Server.packets public class SubPacket { - public const int SUBPACKET_SIZE = 0x20; + public const int SUBPACKET_SIZE = 0x10; + public const int GAMEMESSAGE_SIZE = 0x10; public SubPacketHeader header; + public GameMessageHeader gameMessage; public byte[] data; public unsafe SubPacket(byte[] bytes, ref int offset) @@ -41,11 +48,27 @@ namespace FFXIVClassic_Lobby_Server.packets header = (SubPacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader)); } + if (header.type == 0x3) + { + fixed (byte* pdata = &bytes[offset + SUBPACKET_SIZE]) + { + gameMessage = (GameMessageHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(GameMessageHeader)); + } + } + if (bytes.Length < offset + header.subpacketSize) throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data"); - data = new byte[header.subpacketSize - SUBPACKET_SIZE]; - Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length); + if (header.type == 0x3) + { + data = new byte[header.subpacketSize - SUBPACKET_SIZE - GAMEMESSAGE_SIZE]; + Array.Copy(bytes, offset + SUBPACKET_SIZE + GAMEMESSAGE_SIZE, data, 0, data.Length); + } + else + { + data = new byte[header.subpacketSize - SUBPACKET_SIZE]; + Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length); + } offset += header.subpacketSize; } @@ -53,21 +76,23 @@ namespace FFXIVClassic_Lobby_Server.packets public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data) { this.header = new SubPacketHeader(); - header.opcode = opcode; + this.gameMessage = new GameMessageHeader(); + + gameMessage.opcode = opcode; header.sourceId = sourceId; header.targetId = targetId; - header.timestamp = Utils.UnixTimeStampUTC(); + gameMessage.timestamp = Utils.UnixTimeStampUTC(); - header.unknown0 = 0x03; + header.type = 0x03; header.unknown1 = 0x00; - header.unknown4 = 0x14; - header.unknown5 = 0x00; - header.unknown6 = 0x00; + gameMessage.unknown4 = 0x14; + gameMessage.unknown5 = 0x00; + gameMessage.unknown6 = 0x00; this.data = data; - header.subpacketSize = (ushort)(0x20 + data.Length); + header.subpacketSize = (ushort)(SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length); } public byte[] getHeaderBytes() @@ -82,11 +107,27 @@ namespace FFXIVClassic_Lobby_Server.packets return arr; } + public byte[] getGameMessageBytes() + { + int size = Marshal.SizeOf(gameMessage); + byte[] arr = new byte[size]; + + IntPtr ptr = Marshal.AllocHGlobal(size); + Marshal.StructureToPtr(gameMessage, ptr, true); + Marshal.Copy(ptr, arr, 0, size); + Marshal.FreeHGlobal(ptr); + return arr; + } + public byte[] getBytes() { byte[] outBytes = new byte[header.subpacketSize]; Array.Copy(getHeaderBytes(), 0, outBytes, 0, SUBPACKET_SIZE); - Array.Copy(data, 0, outBytes, SUBPACKET_SIZE, data.Length); + + if (header.type == 0x3) + Array.Copy(getGameMessageBytes(), 0, outBytes, SUBPACKET_SIZE, GAMEMESSAGE_SIZE); + + Array.Copy(data, 0, outBytes, SUBPACKET_SIZE + header.type == 0x3 ? GAMEMESSAGE_SIZE : 0, data.Length); return outBytes; } @@ -94,8 +135,12 @@ namespace FFXIVClassic_Lobby_Server.packets { #if DEBUG Console.BackgroundColor = ConsoleColor.DarkRed; - Console.WriteLine("Size: 0x{0:X}, Opcode: 0x{1:X}", header.subpacketSize, header.opcode); + Console.WriteLine("Size: 0x{0:X}", header.subpacketSize); + if (header.type == 0x03) + Console.WriteLine("Opcode: 0x{0:X}", gameMessage.opcode); Console.WriteLine("{0}", Utils.ByteArrayToHex(getHeaderBytes())); + if (header.type == 0x03) + Console.WriteLine("{0}", Utils.ByteArrayToHex(getGameMessageBytes())); Console.BackgroundColor = ConsoleColor.DarkMagenta; Console.WriteLine("{0}", Utils.ByteArrayToHex(data)); Console.BackgroundColor = ConsoleColor.Black; diff --git a/FFXIVClassic Map Server/packets/send/login/InitPacket.cs b/FFXIVClassic Map Server/packets/send/login/InitPacket.cs index 849224da..2ffa98ab 100644 --- a/FFXIVClassic Map Server/packets/send/login/InitPacket.cs +++ b/FFXIVClassic Map Server/packets/send/login/InitPacket.cs @@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.packets.send.login { public static BasePacket buildPacket(uint unknown, uint time) { - byte[] data = new byte[18]; + byte[] data = new byte[0x18]; using (MemoryStream mem = new MemoryStream(data)) {