From d90dc0cb80a490257b7af0d9aff0ab07c4c1eb65 Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Tue, 19 Jan 2016 21:47:59 -0500 Subject: [PATCH] Redid the initial handshake code to handle the found connection type field. Server should no longer create two player objects and code has been reduced. Removed instances of connection1/2 getters... server simply sends packets down zone connection. Fixed issue with world manager not zoning in player due to missing 0x2 packet. --- FFXIVClassic Map Server/PacketProcessor.cs | 80 ++++++++----------- FFXIVClassic Map Server/Program.cs | 12 ++- FFXIVClassic Map Server/Server.cs | 19 ++--- .../actors/chara/player/Player.cs | 51 ++++++------ .../dataobjects/ConnectedPlayer.cs | 57 +++++-------- FFXIVClassic Map Server/lua/LuaPlayer.cs | 4 +- FFXIVClassic Map Server/packets/BasePacket.cs | 6 +- 7 files changed, 102 insertions(+), 127 deletions(-) diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index d286a0bf..787a6b52 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -55,11 +55,7 @@ namespace FFXIVClassic_Lobby_Server } public void processPacket(ClientConnection client, BasePacket packet) - { - ConnectedPlayer player = null; - if (client.owner != 0 && mPlayers.ContainsKey(client.owner)) - player = mPlayers[client.owner]; - + { if (packet.header.isCompressed == 0x01) BasePacket.decryptPacket(client.blowfish, ref packet); @@ -80,6 +76,7 @@ namespace FFXIVClassic_Lobby_Server BasePacket reply1 = new BasePacket(reply1Data); BasePacket reply2 = new BasePacket("./packets/login/login2.bin"); + //Write Timestamp into Reply1 using (MemoryStream mem = new MemoryStream(reply1.data)) { using (BinaryWriter binReader = new BinaryWriter(mem)) @@ -87,25 +84,9 @@ namespace FFXIVClassic_Lobby_Server binReader.BaseStream.Seek(0x14, SeekOrigin.Begin); binReader.Write((UInt32)Utils.UnixTimeStampUTC()); } - } - - //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(reply1); - client.queuePacket(reply2); - break; - } + } + //Read in Actor Id that owns this connection uint actorID = 0; using (MemoryStream mem = new MemoryStream(packet.data)) { @@ -123,9 +104,13 @@ namespace FFXIVClassic_Lobby_Server } } + //Should never happen.... unless actor id IS 0! if (actorID == 0) break; + + client.owner = actorID; + //Write Actor ID into reply2 using (MemoryStream mem = new MemoryStream(reply2.data)) { using (BinaryWriter binReader = new BinaryWriter(mem)) @@ -135,23 +120,29 @@ namespace FFXIVClassic_Lobby_Server } } - if (((IPEndPoint)client.socket.LocalEndPoint).Port == 54992) + ConnectedPlayer player = null; + + if (packet.header.connectionType == BasePacket.TYPE_ZONE) { - player = new ConnectedPlayer(actorID); - mPlayers[actorID] = player; - client.owner = actorID; - client.connType = 0; - player.setConnection1(client); - Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress())); - } - else - { - client.owner = actorID; - client.connType = 1; - player.setConnection2(client); + while (!mPlayers.ContainsKey(client.owner)) + { } + player = mPlayers[client.owner]; } - //Get Character info + //Create connected player if not created + if (player == null) + { + player = new ConnectedPlayer(actorID); + mPlayers[actorID] = player; + } + + player.setConnection(packet.header.connectionType, client); + + if (packet.header.connectionType == BasePacket.TYPE_ZONE) + Log.debug(String.Format("Got {0} connection for ActorID {1} @ {2}.", "zone", actorID, client.getAddress())); + else if (packet.header.connectionType == BasePacket.TYPE_CHAT) + Log.debug(String.Format("Got {0} connection for ActorID {1} @ {2}.", "chat", actorID, client.getAddress())); + //Create player actor reply1.debugPrintPacket(); client.queuePacket(reply1); @@ -172,6 +163,8 @@ namespace FFXIVClassic_Lobby_Server } else if (subpacket.header.type == 0x03) { + ConnectedPlayer player = mPlayers[client.owner]; + //Normal Game Opcode switch (subpacket.gameMessage.opcode) { @@ -357,17 +350,14 @@ namespace FFXIVClassic_Lobby_Server } } - public void sendPacket(string path, int conn) + public void sendPacket(string path) { BasePacket packet = new BasePacket(path); foreach (KeyValuePair entry in mPlayers) { packet.replaceActorID(entry.Value.actorID); - if (conn == 1 || conn == 3) - entry.Value.getConnection1().queuePacket(packet); - if (conn == 2 || conn == 3) - entry.Value.getConnection2().queuePacket(packet); + entry.Value.queuePacket(packet); } } @@ -438,10 +428,8 @@ namespace FFXIVClassic_Lobby_Server packet.replaceActorID(entry.Value.actorID); actorPacket.replaceActorID(entry.Value.actorID); - entry.Value.getConnection1().queuePacket(packet); - entry.Value.getConnection1().queuePacket(actorPacket); - - + entry.Value.queuePacket(packet); + entry.Value.queuePacket(actorPacket); } } diff --git a/FFXIVClassic Map Server/Program.cs b/FFXIVClassic Map Server/Program.cs index 4999ba82..fca7e806 100644 --- a/FFXIVClassic Map Server/Program.cs +++ b/FFXIVClassic Map Server/Program.cs @@ -74,19 +74,23 @@ namespace FFXIVClassic_Lobby_Server String input = Console.ReadLine(); String[] split = input.Split(' '); - if (split.Length >= 3) + if (split.Length >= 2) { if (split[0].Equals("sendpacket")) { - try{ - server.sendPacket("./packets/" + split[1], Int32.Parse(split[2])); + try + { + server.sendPacket("./packets/" + split[1]); } catch (Exception e) { Log.error("Could not load packet: " + e); } } - else if (split[0].Equals("warp")) + } + else if (split.Length >= 3) + { + if (split[0].Equals("warp")) { server.doWarp(split[1], split[2], split[3], split[4]); } diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index 0d2118cf..52cf707a 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -35,7 +35,7 @@ namespace FFXIVClassic_Lobby_Server #region Socket Handling public bool startServer() { - mWorldManager = new WorldManager(); + mWorldManager = new WorldManager(this); mWorldManager.LoadZoneList(); IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), FFXIV_MAP_PORT); @@ -226,9 +226,9 @@ namespace FFXIVClassic_Lobby_Server #endregion - public void sendPacket(string path, int conn) + public void sendPacket(string path) { - mProcessor.sendPacket(path, conn); + mProcessor.sendPacket(path); } public void testCodePacket(uint id, uint value, string target) @@ -245,14 +245,8 @@ namespace FFXIVClassic_Lobby_Server BasePacket packet = BasePacket.createPacket(changePropertyPacket, true, false); packet.debugPrintPacket(); - if (entry.Value.getConnection1() != null) - entry.Value.getConnection1().queuePacket(packet); - else - Log.error("Connection was null"); - if (entry.Value.getConnection2() != null) - entry.Value.getConnection2().queuePacket(packet); - else - Log.error("Connection was null"); + + entry.Value.queuePacket(packet); } } @@ -268,8 +262,7 @@ namespace FFXIVClassic_Lobby_Server SubPacket changePropertyPacket = changeProperty.buildPacket((entry.Value.actorID), (entry.Value.actorID)); BasePacket packet = BasePacket.createPacket(changePropertyPacket, true, false); packet.debugPrintPacket(); - entry.Value.getConnection1().queuePacket(packet); - entry.Value.getConnection2().queuePacket(packet); + entry.Value.queuePacket(packet); } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index aa262a10..c6f09aaa 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -6,6 +6,7 @@ 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.list; +using FFXIVClassic_Map_Server.packets.send.login; using FFXIVClassic_Map_Server.packets.send.player; using FFXIVClassic_Map_Server.utils; using MySql.Data.MySqlClient; @@ -61,8 +62,11 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara public PlayerWork playerWork = new PlayerWork(); - public Player(uint actorID) : base(actorID) + public ConnectedPlayer playerSession; + + public Player(ConnectedPlayer cp, uint actorID) : base(actorID) { + playerSession = cp; actorName = String.Format("_pc{0:00000000}", actorID); className = "Player"; currentSubState = SetActorStatePacket.SUB_STATE_PLAYER; @@ -360,14 +364,13 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara } public void sendZoneInPackets(WorldManager world) - { - ClientConnection client; - client.queuePacket(SetMapPacket.buildPacket(actorId, zone.regionId, zone.actorId), true, false); - //client.queuePacket(_0x2Packet.buildPacket(player.actorID), true, false); - client.queuePacket(SetMusicPacket.buildPacket(actorId, 0x3D, 0x01), true, false); - client.queuePacket(SetWeatherPacket.buildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR), true, false); + { + playerSession.queuePacket(SetMapPacket.buildPacket(actorId, zone.regionId, zone.actorId), true, false); + playerSession.queuePacket(_0x2Packet.buildPacket(actorId), true, false); + playerSession.queuePacket(SetMusicPacket.buildPacket(actorId, 0x3D, 0x01), true, false); + playerSession.queuePacket(SetWeatherPacket.buildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR), true, false); - client.queuePacket(getSpawnPackets(actorId)); + playerSession.queuePacket(getSpawnPackets(actorId)); #region grouptest //Retainers @@ -377,19 +380,19 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara retainerListEntries.Add(new ListEntry(0x24, 0x0, 0xFFFFFFFF, false, false, "TEST2")); retainerListEntries.Add(new ListEntry(0x25, 0x0, 0xFFFFFFFF, false, false, "TEST3")); BasePacket retainerListPacket = BasePacket.createPacket(ListUtils.createRetainerList(actorId, 0xF4, 1, 0x800000000004e639, retainerListEntries), true, false); - client.queuePacket(retainerListPacket); + playerSession.queuePacket(retainerListPacket); //Party List partyListEntries = new List(); partyListEntries.Add(new ListEntry(actorId, 0xFFFFFFFF, 0xFFFFFFFF, false, true, customDisplayName)); partyListEntries.Add(new ListEntry(0x029B27D3, 0xFFFFFFFF, 0x195, false, true, "Valentine Bluefeather")); BasePacket partyListPacket = BasePacket.createPacket(ListUtils.createPartyList(actorId, 0xF4, 1, 0x8000000000696df2, partyListEntries), true, false); - client.queuePacket(partyListPacket); + playerSession.queuePacket(partyListPacket); #endregion #region itemsetup ////////ITEMS//////// - client.queuePacket(InventoryBeginChangePacket.buildPacket(actorId), true, false); + playerSession.queuePacket(InventoryBeginChangePacket.buildPacket(actorId), true, false); //TEST @@ -433,7 +436,7 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara #endregion #region equipsetup - client.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); + playerSession.queuePacket(BasePacket.createPacket(setinvPackets, true, false)); EquipmentSetupPacket initialEqupmentPacket = new EquipmentSetupPacket(); initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_BODY, 5); initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_HEAD, 3); @@ -443,23 +446,23 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara initialEqupmentPacket.setItem(EquipmentSetupPacket.SLOT_LEGS, 8); //Equip Init - client.queuePacket(InventorySetBeginPacket.buildPacket(actorId, 0x23, InventorySetBeginPacket.CODE_EQUIPMENT), true, false); - client.queuePacket(BasePacket.createPacket(initialEqupmentPacket.buildPackets(actorId), true, false)); - client.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); - client.queuePacket(InventoryEndChangePacket.buildPacket(actorId), true, false); + playerSession.queuePacket(InventoryEndChangePacket.buildPacket(actorId), true, false); ////////ITEMS//////// #endregion - client.queuePacket(getInitPackets(actorId)); + playerSession.queuePacket(getInitPackets(actorId)); BasePacket innSpawn = zone.getSpawnPackets(actorId); BasePacket debugSpawn = world.GetDebugActor().getSpawnPackets(actorId); - BasePacket worldMasterSpawn = world.GetActor().getSpawnPackets(actorId); - client.queuePacket(innSpawn); - client.queuePacket(debugSpawn); - client.queuePacket(worldMasterSpawn); + BasePacket worldMasterSpawn = world.GetActor().getSpawnPackets(actorId); + playerSession.queuePacket(innSpawn); + playerSession.queuePacket(debugSpawn); + playerSession.queuePacket(worldMasterSpawn); #region hardcode BasePacket reply9 = new BasePacket("./packets/login/login9_zonesetup.bin"); //Bed, Book created @@ -468,9 +471,9 @@ namespace FFXIVClassic_Map_Server.dataobjects.chara reply9.replaceActorID(actorId); reply10.replaceActorID(actorId); reply11.replaceActorID(actorId); - client.queuePacket(reply9); - client.queuePacket(reply10); - client.queuePacket(reply11); + playerSession.queuePacket(reply9); + playerSession.queuePacket(reply10); + playerSession.queuePacket(reply11); #endregion } diff --git a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs index 36e1fa14..c4ee21b1 100644 --- a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs +++ b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs @@ -19,68 +19,51 @@ namespace FFXIVClassic_Map_Server.dataobjects public uint eventCurrentOwner = 0; public string eventCurrentStarter = ""; - ClientConnection conn1; - ClientConnection conn2; + private ClientConnection zoneConnection; + private ClientConnection chatConnection; bool isDisconnected; public ConnectedPlayer(uint actorId) { this.actorID = actorId; - playerActor = new Player(actorId); + playerActor = new Player(this, actorId); actorInstanceList.Add(playerActor); } - public void addConnection(ClientConnection conn) + public void setConnection(int type, ClientConnection conn) { - if (conn1 == null && conn2 != null) - conn1 = conn; - else if (conn2 == null && conn1 != null) - conn2 = conn; - else - conn1 = conn; + switch (type) + { + case BasePacket.TYPE_ZONE: + zoneConnection = conn; + break; + case BasePacket.TYPE_CHAT: + chatConnection = conn; + break; + } } - + public bool isClientConnectionsReady() { - return (conn1 != null && conn2 != null); + return (zoneConnection != null && chatConnection != null); } public void disconnect() { isDisconnected = true; - conn1.disconnect(); - conn2.disconnect(); - } - - public void setConnection1(ClientConnection conn) - { - conn1 = conn; - } - - public void setConnection2(ClientConnection conn) - { - conn2 = conn; - } - - public ClientConnection getConnection1() - { - return conn1; - } - - public ClientConnection getConnection2() - { - return conn2; - } + zoneConnection.disconnect(); + chatConnection.disconnect(); + } public void queuePacket(BasePacket basePacket) { - conn1.queuePacket(basePacket); + zoneConnection.queuePacket(basePacket); } public void queuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted) { - conn1.queuePacket(subPacket, isAuthed, isEncrypted); + zoneConnection.queuePacket(subPacket, isAuthed, isEncrypted); } public Player getActor() diff --git a/FFXIVClassic Map Server/lua/LuaPlayer.cs b/FFXIVClassic Map Server/lua/LuaPlayer.cs index 187e31e8..e157ccce 100644 --- a/FFXIVClassic Map Server/lua/LuaPlayer.cs +++ b/FFXIVClassic Map Server/lua/LuaPlayer.cs @@ -62,12 +62,12 @@ namespace FFXIVClassic_Map_Server.lua public void runEvent(string functionName, params object[] parameters) { List lParams = LuaUtils.createLuaParamList(parameters); - player.getConnection1().queuePacket(RunEventFunctionPacket.buildPacket(player.actorID, player.eventCurrentOwner, player.eventCurrentStarter, functionName, lParams), true, false); + player.queuePacket(RunEventFunctionPacket.buildPacket(player.actorID, player.eventCurrentOwner, player.eventCurrentStarter, functionName, lParams), true, false); } public void endEvent() { - player.getConnection1().queuePacket(EndEventPacket.buildPacket(player.actorID, player.eventCurrentOwner, player.eventCurrentStarter), true, false); + player.queuePacket(EndEventPacket.buildPacket(player.actorID, player.eventCurrentOwner, player.eventCurrentStarter), true, false); } } diff --git a/FFXIVClassic Map Server/packets/BasePacket.cs b/FFXIVClassic Map Server/packets/BasePacket.cs index 384a0df0..b06121d3 100644 --- a/FFXIVClassic Map Server/packets/BasePacket.cs +++ b/FFXIVClassic Map Server/packets/BasePacket.cs @@ -10,18 +10,22 @@ using System.IO; namespace FFXIVClassic_Lobby_Server.packets { + [StructLayout(LayoutKind.Sequential)] public struct BasePacketHeader { public byte isAuthenticated; public byte isCompressed; - public ushort reserved; + public ushort connectionType; public ushort packetSize; public ushort numSubpackets; public ulong timestamp; //Miliseconds } public class BasePacket{ + + public const int TYPE_ZONE = 1; + public const int TYPE_CHAT = 2; public const int BASEPACKET_SIZE = 0x10; public BasePacketHeader header;