diff --git a/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj b/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj index cbf0bda1..3dd9aa16 100644 --- a/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj +++ b/FFXIVClassic_Lobby_Server/FFXIVClassic_Lobby_Server.csproj @@ -63,6 +63,8 @@ + + diff --git a/FFXIVClassic_Lobby_Server/PacketProcessor.cs b/FFXIVClassic_Lobby_Server/PacketProcessor.cs index 0912b786..25e54f6e 100644 --- a/FFXIVClassic_Lobby_Server/PacketProcessor.cs +++ b/FFXIVClassic_Lobby_Server/PacketProcessor.cs @@ -133,7 +133,7 @@ namespace FFXIVClassic_Lobby_Server if (userId == 0) { - client.disconnect(); + //client.disconnect(); Console.WriteLine("Invalid session, kicking..."); } @@ -147,12 +147,13 @@ namespace FFXIVClassic_Lobby_Server { Console.WriteLine("{0} => Get characters", client.currentUserId == 0 ? client.getAddress() : "User " + client.currentUserId); - sendWorldList(client, packet); - sendCharacterList(client, packet); + sendWorldList(client, packet); BasePacket outgoingPacket = new BasePacket("./packets/getCharsPacket.bin"); BasePacket.encryptPacket(client.blowfish, outgoingPacket); client.queuePacket(outgoingPacket); + + //sendCharacterList(client, packet); } private void ProcessSelectCharacter(ClientConnection client, SubPacket packet) @@ -216,33 +217,54 @@ namespace FFXIVClassic_Lobby_Server } //Confirm Reserve - BasePacket confirmReservePacket = new BasePacket("./packets/chara/confirmReserve.bin"); + CharaCreatorPacket confirmReserve = new CharaCreatorPacket(charaReq.sequence, CharaCreatorPacket.RESERVE, 1, 1, 1, name, "World Name"); + BasePacket confirmReservePacket = BasePacket.createPacket(confirmReserve.buildPacket(), true, false); BasePacket.encryptPacket(client.blowfish, confirmReservePacket); client.queuePacket(confirmReservePacket); + Console.WriteLine("User {0} => Reserving character \"{1}\"", client.currentUserId, charaReq.characterName); break; case 0x02://Make Character character = Character.EncodedToCharacter(charaReq.characterInfoEncoded); + Database.makeCharacter(client.currentUserId, name, character); //Confirm - BasePacket confirmMakePacket = new BasePacket("./packets/chara/confirmMake.bin"); + CharaCreatorPacket makeChara = new CharaCreatorPacket(charaReq.sequence, CharaCreatorPacket.MAKE, 1, 1, 1, name, "World Name"); + BasePacket confirmMakePacket = BasePacket.createPacket(makeChara.buildPacket(), true, false); BasePacket.encryptPacket(client.blowfish, confirmMakePacket); client.queuePacket(confirmMakePacket); + Console.WriteLine("User {0} => Character created!", client.currentUserId); break; case 0x03://Rename + + //Confirm + CharaCreatorPacket renameChara = new CharaCreatorPacket(charaReq.sequence, CharaCreatorPacket.RENAME, 1, 1, 1, name, "World Name"); + BasePacket confirmRenamePacket = BasePacket.createPacket(renameChara.buildPacket(), true, false); + BasePacket.encryptPacket(client.blowfish, confirmRenamePacket); + client.queuePacket(confirmRenamePacket); + + Console.WriteLine("User {0} => Character renamed to \"{1}\"", client.currentUserId, charaReq.characterName); break; case 0x04://Delete Database.deleteCharacter(charaReq.characterId, charaReq.characterName); //Confirm - BasePacket deleteConfirmPacket = new BasePacket("./packets/chara/confirmDelete.bin"); - BasePacket.encryptPacket(client.blowfish, deleteConfirmPacket); - client.queuePacket(deleteConfirmPacket); + CharaCreatorPacket deleteChara = new CharaCreatorPacket(charaReq.sequence, CharaCreatorPacket.MAKE, 1, 1, 1, name, "World Name"); + BasePacket confirmDeletePacket = BasePacket.createPacket(deleteChara.buildPacket(), true, false); + BasePacket.encryptPacket(client.blowfish, confirmDeletePacket); + client.queuePacket(confirmDeletePacket); + Console.WriteLine("User {0} => Character deleted \"{1}\"", client.currentUserId, charaReq.characterName); break; case 0x06://Rename Retainer + + //Confirm + CharaCreatorPacket renameRetainerChara = new CharaCreatorPacket(charaReq.sequence, CharaCreatorPacket.RENAME_RETAINER, 1, 1, 1, name, "World Name"); + BasePacket confirmRenameRetainerPacket = BasePacket.createPacket(renameRetainerChara.buildPacket(), true, false); + BasePacket.encryptPacket(client.blowfish, confirmRenameRetainerPacket); + client.queuePacket(confirmRenameRetainerPacket); break; } } @@ -279,7 +301,7 @@ namespace FFXIVClassic_Lobby_Server CharacterListPacket characterlistPacket = new CharacterListPacket(1, charaList); List subPackets = characterlistPacket.buildPackets(); - + subPackets[0].debugPrintSubPacket(); BasePacket basePacket = BasePacket.createPacket(subPackets, true, false); BasePacket.encryptPacket(client.blowfish, basePacket); client.queuePacket(basePacket); diff --git a/FFXIVClassic_Lobby_Server/Server.cs b/FFXIVClassic_Lobby_Server/Server.cs index ce77cb5c..302efd77 100644 --- a/FFXIVClassic_Lobby_Server/Server.cs +++ b/FFXIVClassic_Lobby_Server/Server.cs @@ -23,7 +23,7 @@ namespace FFXIVClassic_Lobby_Server #region Socket Handling public bool startServer() { - IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse("141.117.161.40"), FFXIV_LOBBY_PORT); + IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse("127.0.0.1"), FFXIV_LOBBY_PORT); try{ mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); diff --git a/FFXIVClassic_Lobby_Server/packets/CharaCreatorPacket.cs b/FFXIVClassic_Lobby_Server/packets/CharaCreatorPacket.cs new file mode 100644 index 00000000..ae46b83b --- /dev/null +++ b/FFXIVClassic_Lobby_Server/packets/CharaCreatorPacket.cs @@ -0,0 +1,67 @@ +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 CharaCreatorPacket + { + public const ushort OPCODE = 0x0E; + + public const ushort RESERVE = 0x01; + public const ushort MAKE = 0x02; + public const ushort RENAME = 0x03; + public const ushort DELETE = 0x04; + public const ushort RENAME_RETAINER = 0x06; + + private UInt64 sequence; + + private ushort command; + private uint pid; + private uint cid; + private uint type; + private uint ticket; + private string charaName; + private string worldName; + + public CharaCreatorPacket(UInt64 sequence, ushort command, uint pid, uint cid, uint ticket, string charaName, string worldName) + { + this.sequence = sequence; + this.command = command; + this.pid = pid; + this.cid = cid; + this.type = 0x400000; + this.ticket = ticket; + this.charaName = charaName; + this.worldName = worldName; + } + + public SubPacket buildPacket() + { + MemoryStream memStream = new MemoryStream(0x1F0); + BinaryWriter binWriter = new BinaryWriter(memStream); + + binWriter.Write((UInt64)sequence); + binWriter.Write((byte)1); + binWriter.Write((byte)1); + binWriter.Write((UInt16)command); + binWriter.Write((UInt32)0); + + binWriter.Write((UInt32)pid); //PID + binWriter.Write((UInt32)cid); //CID + binWriter.Write((UInt32)type); //Type? + binWriter.Write((UInt32)ticket); //Ticket + binWriter.Write(Encoding.ASCII.GetBytes(charaName.PadRight(0x20, '\0'))); //Name + binWriter.Write(Encoding.ASCII.GetBytes(worldName.PadRight(0x20, '\0'))); //World Name + + byte[] data = memStream.GetBuffer(); + binWriter.Dispose(); + memStream.Dispose(); + + return new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data); + } + } +} diff --git a/FFXIVClassic_Lobby_Server/packets/CharacterListPacket.cs b/FFXIVClassic_Lobby_Server/packets/CharacterListPacket.cs index 61ea5612..2cb0470a 100644 --- a/FFXIVClassic_Lobby_Server/packets/CharacterListPacket.cs +++ b/FFXIVClassic_Lobby_Server/packets/CharacterListPacket.cs @@ -11,7 +11,7 @@ namespace FFXIVClassic_Lobby_Server.packets class CharacterListPacket { public const ushort OPCODE = 0x0D; - public const ushort MAXPERPACKET = 3; + public const ushort MAXPERPACKET = 2; private ulong sequence; private List characterList; @@ -42,21 +42,22 @@ namespace FFXIVClassic_Lobby_Server.packets //Write List Info binWriter.Write((UInt64)sequence); binWriter.Write(characterList.Count - totalCount <= MAXPERPACKET ? (byte)(characterList.Count + 1) : (byte)0); + //binWriter.Write((byte)1); binWriter.Write(characterList.Count - totalCount <= MAXPERPACKET ? (UInt32)(characterList.Count - totalCount) : (UInt32)MAXPERPACKET); - binWriter.Write((byte)6); - binWriter.Write((UInt16)5); + binWriter.Write((byte)0); + binWriter.Write((UInt16)0); } binWriter.Seek(0x10 + (0x1D0 * characterCount), SeekOrigin.Begin); //Write Entries - binWriter.Write((uint)0); - binWriter.Write((uint)totalCount); - binWriter.Write((uint)0); - binWriter.Write((uint)0); - binWriter.Write(Encoding.ASCII.GetBytes(chara.name.PadRight(0x20, '\0'))); - binWriter.Write(Encoding.ASCII.GetBytes(chara.world.PadRight(0x10, '\0'))); - binWriter.Write("wAQAAOonIyMNAAAAV3Jlbml4IFdyb25nABwAAAAEAAAAAwAAAAMAAAA_8OADAAHQFAAEAAABAAAAABTQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGEgAAAAMQAAQCQAAMAsAACKVAAAAPgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAkAwAAAAAAAAAAANvb1M05AQAABBoAAAEABqoiIuIKAAAAcHJ2MElubjAxABEAAABkZWZhdWx0VGVycml0b3J5AAwJAhcABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAAAAAAAAA="); + binWriter.Write((uint)0); //??? + binWriter.Write((uint)(totalCount + 1)); //Character Id + binWriter.Write((uint)totalCount); //Slot + binWriter.Write((uint)0); //Options (0x01: Service Account not active, 0x72: Change Chara Name) + binWriter.Write(Encoding.ASCII.GetBytes(chara.name.PadRight(0x20, '\0'))); //Name + binWriter.Write(Encoding.ASCII.GetBytes(chara.world.PadRight(0xE, '\0'))); //World Name + binWriter.Write("wAQAAOonIyMNAAAAV3Jlbml4IFdyb25nABwAAAAEAAAAAwAAAAMAAAA_8OADAAHQFAAEAAABAAAAABTQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGEgAAAAMQAAQCQAAMAsAACKVAAAAPgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAkAwAAAAAAAAAAANvb1M05AQAABBoAAAEABqoiIuIKAAAAcHJ2MElubjAxABEAAABkZWZhdWx0VGVycml0b3J5AAwJAhcABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAAAAAAAAA="); //Appearance Data characterCount++; totalCount++;