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++;