diff --git a/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj b/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj index 573a078e..de26b36a 100644 --- a/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj +++ b/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj @@ -62,9 +62,11 @@ + + diff --git a/FFXIVClassic_Lobby_Server/PacketProcessor.cs b/FFXIVClassic_Lobby_Server/PacketProcessor.cs index d8eb4361..f989a3bf 100644 --- a/FFXIVClassic_Lobby_Server/PacketProcessor.cs +++ b/FFXIVClassic_Lobby_Server/PacketProcessor.cs @@ -147,7 +147,7 @@ namespace FFXIVClassic_Lobby_Server { Console.WriteLine("{0} => Get characters", client.currentUserId == 0 ? client.getAddress() : "User " + client.currentUserId); - buildWorldLists(client, packet); + sendWorldList(client, packet); BasePacket outgoingPacket = new BasePacket("./packets/getCharsPacket.bin"); BasePacket.encryptPacket(client.blowfish, outgoingPacket); @@ -203,14 +203,8 @@ namespace FFXIVClassic_Lobby_Server if (alreadyTaken) { - PacketStructs.ErrorPacket errorPacket = new PacketStructs.ErrorPacket(); - errorPacket.sequence = charaReq.sequence; - errorPacket.errorId = 13005; - errorPacket.errorCode = 0; - errorPacket.statusCode = 0; - byte[] data = PacketStructs.StructureToByteArray(errorPacket); - - SubPacket subpacket = new SubPacket(0x02, packet.header.sourceId, packet.header.targetId, data); + ErrorPacket errorPacket = new ErrorPacket(charaReq.sequence, 13005, 0, 0, ""); + SubPacket subpacket = errorPacket.buildPacket(); BasePacket basePacket = BasePacket.createPacket(subpacket, true, false); basePacket.debugPrintPacket(); BasePacket.encryptPacket(client.blowfish, basePacket); @@ -250,58 +244,32 @@ namespace FFXIVClassic_Lobby_Server case 0x06://Rename Retainer break; } + } + + private void sendWorldList(ClientConnection client, SubPacket packet) + { + List serverList = Database.getServers(); + WorldListPacket worldlistPacket = new WorldListPacket(serverList); + List subPackets = worldlistPacket.buildPackets(); + + BasePacket basePacket = BasePacket.createPacket(subPackets, true, false); + BasePacket.encryptPacket(client.blowfish, basePacket); + client.queuePacket(basePacket); } - private void buildWorldLists(ClientConnection client, SubPacket packet) + private void sendUnknownList(ClientConnection client, SubPacket packet) { - List serverList = Database.getServers(); - int serverCount = 0; - int totalCount = 0; - PacketStructs.WorldListPacket worldListPacket = new PacketStructs.WorldListPacket(); - uint isEndList = serverList.Count <= 6 ? (byte)(serverList.Count+1) : (byte)0; - uint numWorlds = serverList.Count <= 6 ? (byte)serverList.Count : (byte)6; - numWorlds <<= 8; + } - worldListPacket.isEndListANDNumWorlds = (uint)(isEndList | numWorlds); - worldListPacket.sequence = 0; - worldListPacket.unknown1 = 0; - worldListPacket.worlds = new PacketStructs.WorldListEntry[6]; + private void sendRetainerList(ClientConnection client, SubPacket packet) + { + + } - foreach (World world in serverList) - { - //Insert world entry - PacketStructs.WorldListEntry entry = new PacketStructs.WorldListEntry(); - entry.id = world.id; - entry.listPosition = world.listPosition; - entry.population = world.population; - entry.name = world.name; - worldListPacket.worlds[serverCount] = entry; + private void sendCharacterList(ClientConnection client, SubPacket packet) + { - serverCount++; - totalCount++; - if (serverCount % 6 == 0 || totalCount >= serverList.Count) - { - //Send this chunk of world list - byte[] data = PacketStructs.StructureToByteArray(worldListPacket); - SubPacket subpacket = new SubPacket(0x15, 0xe0006868, 0xe0006868, data); - BasePacket basePacket = BasePacket.createPacket(subpacket, true, false); - BasePacket.encryptPacket(client.blowfish, basePacket); - client.queuePacket(basePacket); - - //Make new worldlist if still remaining - if (totalCount <= serverList.Count) - { - worldListPacket = new PacketStructs.WorldListPacket(); - isEndList = serverList.Count <= 6 ? (byte)(serverList.Count + 1) : (byte)0; - numWorlds = serverList.Count <= 6 ? (byte)serverList.Count : (byte)6; - numWorlds <<= 8; - worldListPacket.isEndListANDNumWorlds = (uint)(isEndList | numWorlds); - worldListPacket.sequence = 0; - worldListPacket.unknown1 = 0; - } - } - } } } diff --git a/FFXIVClassic_Lobby_Server/packets/ErrorPacket.cs b/FFXIVClassic_Lobby_Server/packets/ErrorPacket.cs new file mode 100644 index 00000000..949b483f --- /dev/null +++ b/FFXIVClassic_Lobby_Server/packets/ErrorPacket.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Lobby_Server.packets +{ + class ErrorPacket + { + private const ushort OPCODE = 0x02; + + private UInt64 sequence; + private uint errorCode; + private uint statusCode; + private uint textId; + private string message; + + public ErrorPacket(UInt64 sequence, uint errorCode, uint statusCode, uint textId, string message) + { + this.sequence = sequence; + this.errorCode = errorCode; + this.statusCode = statusCode; + this.textId = textId; + this.message = message; + } + + public SubPacket buildPacket() + { + MemoryStream memStream = new MemoryStream(0x210); + BinaryWriter binWriter = new BinaryWriter(memStream); + + binWriter.Write(sequence); + binWriter.Write(errorCode); + binWriter.Write(statusCode); + binWriter.Write(textId); + binWriter.Write(message); + + byte[] data = memStream.GetBuffer(); + binWriter.Dispose(); + memStream.Dispose(); + SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data); + return subpacket; + } + } +} diff --git a/FFXIVClassic_Lobby_Server/packets/PacketStructs.cs b/FFXIVClassic_Lobby_Server/packets/PacketStructs.cs index 4bafb243..76e31f4a 100644 --- a/FFXIVClassic_Lobby_Server/packets/PacketStructs.cs +++ b/FFXIVClassic_Lobby_Server/packets/PacketStructs.cs @@ -22,27 +22,6 @@ namespace FFXIVClassic_Lobby_Server.packets public String session; } - [StructLayout(LayoutKind.Sequential)] - public unsafe struct WorldListPacket - { - public UInt64 sequence; - public uint isEndListANDNumWorlds; - public uint unknown1; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - public WorldListEntry[] worlds; - } - - [StructLayout(LayoutKind.Sequential)] - public unsafe struct WorldListEntry - { - public ushort id; - public ushort listPosition; - public uint population; - public UInt64 unknown; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x40)] - public String name; - } - [StructLayout(LayoutKind.Sequential)] public unsafe struct CharacterRequestPacket { @@ -92,17 +71,6 @@ namespace FFXIVClassic_Lobby_Server.packets public String errorMessage; } - [StructLayout(LayoutKind.Sequential)] - public unsafe struct ErrorPacket - { - public UInt64 sequence; - public uint errorCode; - public uint statusCode; - public uint errorId; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x2BB)] - public String errorMessage; - } - public static unsafe CharacterRequestPacket toCharacterRequestStruct(byte[] bytes) { fixed (byte* pdata = &bytes[0]) diff --git a/FFXIVClassic_Lobby_Server/packets/WorldListPacket.cs b/FFXIVClassic_Lobby_Server/packets/WorldListPacket.cs new file mode 100644 index 00000000..530f786d --- /dev/null +++ b/FFXIVClassic_Lobby_Server/packets/WorldListPacket.cs @@ -0,0 +1,94 @@ +using FFXIVClassic_Lobby_Server.dataobjects; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Lobby_Server.packets +{ + class WorldListPacket + { + private List worldList; + + public WorldListPacket(List serverList) + { + this.worldList = serverList; + } + + public List buildPackets() + { + List subPackets = new List(); + + int serverCount = 0; + int totalCount = 0; + + MemoryStream memStream = null; + BinaryWriter binWriter = null; + + foreach (World world in worldList) + { + if (totalCount == 0 || serverCount % 6 == 0) + { + memStream = new MemoryStream(0x210); + binWriter = new BinaryWriter(memStream); + + //Write List Info + binWriter.Write((UInt64)0); + binWriter.Write(worldList.Count - totalCount <= 6 ? (byte)(worldList.Count + 1) : (byte)0); + binWriter.Write(worldList.Count - totalCount <= 6 ? (UInt32)worldList.Count - totalCount : (UInt32)6); + binWriter.Write((byte)0); + binWriter.Write((UInt16)0); + } + + //Write Entries + binWriter.Write((ushort)world.id); + binWriter.Write((ushort)world.listPosition); + binWriter.Write((uint)world.population); + binWriter.Write((UInt64)0); + binWriter.Write(Encoding.ASCII.GetBytes(world.name.PadRight(64, '\0'))); + + serverCount++; + totalCount++; + + //Send this chunk of world list + if (serverCount >= 6) + { + byte[] data = memStream.GetBuffer(); + binWriter.Dispose(); + memStream.Dispose(); + SubPacket subpacket = new SubPacket(0x15, 0xe0006868, 0xe0006868, data); + subPackets.Add(subpacket); + serverCount = 0; + } + + } + + //If there is anything left that was missed or the list is empty + if (serverCount > 0 || worldList.Count == 0) + { + if (worldList.Count == 0) + { + memStream = new MemoryStream(0x210); + binWriter = new BinaryWriter(memStream); + + //Write Empty List Info + binWriter.Write((UInt64)0); + binWriter.Write((byte)1); + binWriter.Write((UInt32)0); + binWriter.Write((byte)0); + binWriter.Write((UInt16)0); + } + + byte[] data = memStream.GetBuffer(); + binWriter.Dispose(); + memStream.Dispose(); + SubPacket subpacket = new SubPacket(0x15, 0xe0006868, 0xe0006868, data); + subPackets.Add(subpacket); + } + + return subPackets; + } + } +}