diff --git a/FFXIVClassic Common Class Lib/BasePacket.cs b/FFXIVClassic Common Class Lib/BasePacket.cs
index a6fb2a89..9f9a4c4c 100644
--- a/FFXIVClassic Common Class Lib/BasePacket.cs
+++ b/FFXIVClassic Common Class Lib/BasePacket.cs
@@ -295,6 +295,41 @@ namespace FFXIVClassic.Common
return packet;
}
+ ///
+ /// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
+ ///
+ /// Current offset in buffer.
+ /// Incoming buffer.
+ /// Returns either a BasePacket or null if not enough data.
+ public static BasePacket CreatePacket(ref int offset, byte[] buffer, int bytesRead)
+ {
+ BasePacket newPacket = null;
+
+ //Too small to even get length
+ if (bytesRead <= offset)
+ return null;
+
+ ushort packetSize = BitConverter.ToUInt16(buffer, offset);
+
+ //Too small to whole packet
+ if (bytesRead < offset + packetSize)
+ return null;
+
+ if (buffer.Length < offset + packetSize)
+ return null;
+
+ try
+ {
+ newPacket = new BasePacket(buffer, ref offset);
+ }
+ catch (OverflowException)
+ {
+ return null;
+ }
+
+ return newPacket;
+ }
+
public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet)
{
var data = packet.data;
diff --git a/FFXIVClassic Common Class Lib/SubPacket.cs b/FFXIVClassic Common Class Lib/SubPacket.cs
index 6cd3ff27..38394e29 100644
--- a/FFXIVClassic Common Class Lib/SubPacket.cs
+++ b/FFXIVClassic Common Class Lib/SubPacket.cs
@@ -153,6 +153,41 @@ namespace FFXIVClassic.Common
return outBytes;
}
+ ///
+ /// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
+ ///
+ /// Current offset in buffer.
+ /// Incoming buffer.
+ /// Returns either a BasePacket or null if not enough data.
+ public static SubPacket CreatePacket(ref int offset, byte[] buffer, int bytesRead)
+ {
+ SubPacket newPacket = null;
+
+ //Too small to even get length
+ if (bytesRead <= offset)
+ return null;
+
+ ushort packetSize = BitConverter.ToUInt16(buffer, offset);
+
+ //Too small to whole packet
+ if (bytesRead < offset + packetSize)
+ return null;
+
+ if (buffer.Length < offset + packetSize)
+ return null;
+
+ try
+ {
+ newPacket = new SubPacket(buffer, ref offset);
+ }
+ catch (OverflowException)
+ {
+ return null;
+ }
+
+ return newPacket;
+ }
+
public void DebugPrintSubPacket()
{
#if DEBUG
@@ -169,6 +204,9 @@ namespace FFXIVClassic.Common
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
ConsoleOutputColor.DarkMagenta);
}
+ else
+ logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE),
+ ConsoleOutputColor.DarkMagenta);
#endif
}
}
diff --git a/FFXIVClassic Map Server/CommandProcessor.cs b/FFXIVClassic Map Server/CommandProcessor.cs
index 3936a2b7..af5860ed 100644
--- a/FFXIVClassic Map Server/CommandProcessor.cs
+++ b/FFXIVClassic Map Server/CommandProcessor.cs
@@ -88,7 +88,7 @@ namespace FFXIVClassic_Map_Server
if (cmd.Any())
{
// if client isnt null, take player to be the player actor
- var player = client?.GetActor();
+ var player = client.GetActor();
if (cmd.Equals("help"))
{
diff --git a/FFXIVClassic Map Server/ConfigConstants.cs b/FFXIVClassic Map Server/ConfigConstants.cs
index cf4006e6..c3ea8d54 100644
--- a/FFXIVClassic Map Server/ConfigConstants.cs
+++ b/FFXIVClassic Map Server/ConfigConstants.cs
@@ -30,7 +30,7 @@ namespace FFXIVClassic_Map_Server
INIFile configIni = new INIFile("./map_config.ini");
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1");
- ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "54992");
+ ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "1989");
ConfigConstants.OPTIONS_TIMESTAMP = configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true");
ConfigConstants.DATABASE_WORLDID = UInt32.Parse(configIni.GetValue("Database", "worldid", "0"));
diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index d71ab75b..ff2afdbc 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -91,7 +91,7 @@
-
+
diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs
index a6673c93..1fb84ba4 100644
--- a/FFXIVClassic Map Server/PacketProcessor.cs
+++ b/FFXIVClassic Map Server/PacketProcessor.cs
@@ -26,393 +26,283 @@ namespace FFXIVClassic_Map_Server
Server mServer;
CommandProcessor cp;
Dictionary mPlayers;
- List mConnections;
- public PacketProcessor(Server server, Dictionary playerList, List connectionList)
+ public PacketProcessor(Server server, Dictionary playerList)
{
mPlayers = playerList;
- mConnections = connectionList;
mServer = server;
cp = new CommandProcessor(playerList);
}
- public void ProcessPacket(ClientConnection client, BasePacket packet)
+ public void ProcessPacket(ZoneConnection client, SubPacket subpacket)
{
- if (packet.header.isCompressed == 0x01)
- BasePacket.DecryptPacket(client.blowfish, ref packet);
+
+ ConnectedPlayer player = null;
- List subPackets = packet.GetSubpackets();
- foreach (SubPacket subpacket in subPackets)
- {
- if (subpacket.header.type == 0x01)
- {
- packet.DebugPrintPacket();
- byte[] reply1Data = {
- 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFD, 0xFF, 0xFF,
- 0xE5, 0x6E, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x0
- };
+ if(mPlayers.ContainsKey(subpacket.header.targetId))
+ player = mPlayers[subpacket.header.targetId];
- byte[] reply2Data = {
- 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2B, 0x5F, 0x26,
- 0x66, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xAF, 0x2B, 0x38, 0x2B, 0x5F, 0x26, 0xB8, 0x8D, 0xF0, 0x2B,
- 0xC8, 0xFD, 0x85, 0xFE, 0xA8, 0x7C, 0x5B, 0x09, 0x38, 0x2B, 0x5F, 0x26, 0xC8, 0xD6, 0xAF, 0x2B,
- 0xB8, 0x8D, 0xF0, 0x2B, 0x88, 0xAF, 0x5E, 0x26
- };
-
- BasePacket reply1 = new BasePacket(reply1Data);
- BasePacket reply2 = new BasePacket(reply2Data);
-
- //Write Timestamp into Reply1
- using (MemoryStream mem = new MemoryStream(reply1.data))
- {
- using (BinaryWriter binReader = new BinaryWriter(mem))
- {
- binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
- binReader.Write((UInt32)Utils.UnixTimeStampUTC());
- }
- }
-
- //Read in Actor Id that owns this connection
- 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)
- { }
- }
- }
-
- //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))
- {
- binReader.BaseStream.Seek(0x10, SeekOrigin.Begin);
- binReader.Write(actorID);
- }
- }
-
- ConnectedPlayer player = null;
-
- if (packet.header.connectionType == BasePacket.TYPE_ZONE)
- {
- while (mPlayers != null && !mPlayers.ContainsKey(client.owner))
- { }
- player = mPlayers[client.owner];
- }
-
- //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)
- Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "zone", actorID, client.GetAddress());
- else if (packet.header.connectionType == BasePacket.TYPE_CHAT)
- Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "chat", actorID, client.GetAddress());
-
- //Create player actor
- reply1.DebugPrintPacket();
- client.QueuePacket(reply1);
- client.QueuePacket(reply2);
- break;
- }
- else if (subpacket.header.type == 0x07)
- {
- BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x08);
- //client.QueuePacket(init);
- }
- else if (subpacket.header.type == 0x08)
+ if (player == null)
{
- //Response, client's current [actorID][time]
- //BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x07);
- //client.QueuePacket(init);
- packet.DebugPrintPacket();
- }
- else if (subpacket.header.type == 0x03)
+ player = new ConnectedPlayer(client, subpacket.header.targetId);
+ }
+
+ subpacket.DebugPrintSubPacket();
+
+ //Normal Game Opcode
+ switch (subpacket.gameMessage.opcode)
{
- ConnectedPlayer player = null;
+ //Ping
+ case 0x0001:
+ //subpacket.DebugPrintSubPacket();
+ PingPacket pingPacket = new PingPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(player.actorID, pingPacket.time), true, false));
+ player.Ping();
+ break;
+ //Unknown
+ case 0x0002:
- if(mPlayers.ContainsKey(client.owner))
- player = mPlayers[client.owner];
+ subpacket.DebugPrintSubPacket();
+
+ player = new ConnectedPlayer(client, subpacket.header.targetId);
+ mPlayers[subpacket.header.targetId] = player;
+
+ client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false);
- if (player == null || !player.IsClientConnectionsReady())
- return;
+ Server.GetWorldManager().DoLogin(player.GetActor());
- //Normal Game Opcode
- 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));
- player.Ping();
- break;
- //Unknown
- case 0x0002:
+ break;
+ //Chat Received
+ case 0x0003:
+ ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data);
+ Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
+ subpacket.DebugPrintSubPacket();
- subpacket.DebugPrintSubPacket();
- client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false);
+ if (chatMessage.message.StartsWith("!"))
+ {
+ if (cp.DoCommand(chatMessage.message, player))
+ return; ;
+ }
- Server.GetWorldManager().DoLogin(player.GetActor());
+ player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false);
-
- break;
- //Chat Received
- case 0x0003:
- ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data);
- Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
- subpacket.DebugPrintSubPacket();
-
- if (chatMessage.message.StartsWith("!"))
- {
- if (cp.DoCommand(chatMessage.message, player))
- continue;
- }
-
- player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false);
-
- break;
- //Langauge Code
- case 0x0006:
- LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
- player.languageCode = langCode.languageCode;
- break;
- //Unknown - Happens a lot at login, then once every time player zones
- case 0x0007:
- //subpacket.DebugPrintSubPacket();
- _0x07Packet unknown07 = new _0x07Packet(subpacket.data);
- break;
+ break;
+ //Langauge Code
+ case 0x0006:
+ LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
+ player.languageCode = langCode.languageCode;
+ break;
+ //Unknown - Happens a lot at login, then once every time player zones
+ case 0x0007:
+ //subpacket.DebugPrintSubPacket();
+ _0x07Packet unknown07 = new _0x07Packet(subpacket.data);
+ break;
+ //Update Position
+ case 0x00CA:
//Update Position
- case 0x00CA:
- //Update Position
- //subpacket.DebugPrintSubPacket();
- UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
- player.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
- player.GetActor().SendInstanceUpdate();
+ //subpacket.DebugPrintSubPacket();
+ UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
+ player.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
+ player.GetActor().SendInstanceUpdate();
+
+ if (player.GetActor().IsInZoneChange())
+ player.GetActor().SetZoneChanging(false);
+
+ break;
+ //Set Target
+ case 0x00CD:
+ //subpacket.DebugPrintSubPacket();
+
+ SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
+ player.GetActor().currentTarget = setTarget.actorID;
+ player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true);
+ break;
+ //Lock Target
+ case 0x00CC:
+ LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
+ player.GetActor().currentLockedTarget = lockTarget.actorID;
+ break;
+ //Start Event
+ case 0x012D:
+ subpacket.DebugPrintSubPacket();
+ EventStartPacket eventStart = new EventStartPacket(subpacket.data);
+
+ /*
+ if (eventStart.error != null)
+ {
+ player.errorMessage += eventStart.error;
+
+ if (eventStart.errorIndex == eventStart.errorNum - 1)
+ Program.Log.Error("\n"+player.errorMessage);
- if (player.GetActor().IsInZoneChange())
- player.GetActor().SetZoneChanging(false);
break;
- //Set Target
- case 0x00CD:
- //subpacket.DebugPrintSubPacket();
+ }
+ */
- SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
- player.GetActor().currentTarget = setTarget.actorID;
- player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true);
- break;
- //Lock Target
- case 0x00CC:
- LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
- player.GetActor().currentLockedTarget = lockTarget.actorID;
- break;
- //Start Event
- case 0x012D:
- subpacket.DebugPrintSubPacket();
- EventStartPacket eventStart = new EventStartPacket(subpacket.data);
-
- /*
- if (eventStart.error != null)
- {
- player.errorMessage += eventStart.error;
-
- if (eventStart.errorIndex == eventStart.errorNum - 1)
- Program.Log.Error("\n"+player.errorMessage);
-
-
- break;
- }
- */
-
- Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
+ Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
- player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
- player.GetActor().currentEventName = eventStart.triggerName;
+ player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
+ player.GetActor().currentEventName = eventStart.triggerName;
+ if (ownerActor == null)
+ {
+ //Is it a instance actor?
+ ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
if (ownerActor == null)
{
- //Is it a instance actor?
- ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
- if (ownerActor == null)
- {
- //Is it a Director?
- if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
- ownerActor = player.GetActor().currentDirector;
- else
- {
- Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
- break;
- }
- }
- }
-
- player.GetActor().StartEvent(ownerActor, eventStart);
-
- Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
- break;
- //Unknown, happens at npc spawn and cutscene play????
- case 0x00CE:
- break;
- //Event Result
- case 0x012E:
- subpacket.DebugPrintSubPacket();
- EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data);
- Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
- /*
- //Is it a static actor? If not look in the player's instance
- Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner);
- if (updateOwnerActor == null)
- {
- updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
-
+ //Is it a Director?
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
- updateOwnerActor = player.GetActor().currentDirector;
-
- if (updateOwnerActor == null)
+ ownerActor = player.GetActor().currentDirector;
+ else
+ {
+ Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
break;
- }
- */
- player.GetActor().UpdateEvent(eventUpdate);
+ }
+ }
+ }
- //LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate);
+ player.GetActor().StartEvent(ownerActor, eventStart);
+
+ Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
+ break;
+ //Unknown, happens at npc spawn and cutscene play????
+ case 0x00CE:
+ break;
+ //Event Result
+ case 0x012E:
+ subpacket.DebugPrintSubPacket();
+ EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data);
+ Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
+ /*
+ //Is it a static actor? If not look in the player's instance
+ Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner);
+ if (updateOwnerActor == null)
+ {
+ updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
+
+ if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
+ updateOwnerActor = player.GetActor().currentDirector;
+
+ if (updateOwnerActor == null)
+ break;
+ }
+ */
+ player.GetActor().UpdateEvent(eventUpdate);
+
+ //LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate);
- break;
- case 0x012F:
- //subpacket.DebugPrintSubPacket();
- ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
- if (paramRequest.paramName.Equals("charaWork/exp"))
- player.GetActor().SendCharaExpInfo();
- break;
- /* RECRUITMENT */
- //Start Recruiting
- case 0x01C3:
- StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false));
- break;
- //End Recruiting
- case 0x01C4:
- client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false));
- break;
- //Party Window Opened, Request State
- case 0x01C5:
- client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(player.actorID, true, true, 1), true, false));
- break;
- //Search Recruiting
- case 0x01C7:
- RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data);
- break;
- //Get Recruitment Details
- case 0x01C8:
- RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data);
- RecruitmentDetails details = new RecruitmentDetails();
- details.recruiterName = "Localhost Character";
- details.purposeId = 2;
- details.locationId = 1;
- details.subTaskId = 1;
- details.comment = "This is a test details packet sent by the server. No implementation has been Created yet...";
- details.num[0] = 1;
- client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(player.actorID, details), true, false));
- break;
- //Accepted Recruiting
- case 0x01C6:
- subpacket.DebugPrintSubPacket();
- break;
- /* SOCIAL STUFF */
- case 0x01C9:
- AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(player.actorID, true, addBlackList.name), true, false));
- break;
- case 0x01CA:
- AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(player.actorID, true, RemoveBlackList.name), true, false));
- break;
- case 0x01CB:
- int offset1 = 0;
- client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(player.actorID, new String[] { "Test" }, ref offset1), true, false));
- break;
- case 0x01CC:
- AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(player.actorID, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false));
- break;
- case 0x01CD:
- AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false));
- break;
- case 0x01CE:
- int offset2 = 0;
- client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(player.actorID, new Tuple[] { new Tuple(01, "Test2") }, ref offset2), true, false));
- break;
- case 0x01CF:
- client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(player.actorID, null), true, false));
- break;
- /* SUPPORT DESK STUFF */
- //Request for FAQ/Info List
- case 0x01D0:
- FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, new string[] { "Testing FAQ1", "Coded style!" }), true, false));
- break;
- //Request for body of a faq/info selection
- case 0x01D1:
- FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, "HERE IS A GIANT BODY. Nothing else to say!"), true, false));
- break;
- //Request issue list
- case 0x01D2:
- GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
- client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false));
- break;
- //Request if GM ticket exists
- case 0x01D3:
- client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, false), true, false));
- break;
- //Request for GM response message
- case 0x01D4:
- client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false));
- break;
- //GM Ticket Sent
- case 0x01D5:
- GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
- Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
- client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, true), true, false));
- break;
- //Request to end ticket
- case 0x01D6:
- client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false));
- break;
- default:
- Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
- subpacket.DebugPrintSubPacket();
- break;
- }
+ break;
+ case 0x012F:
+ //subpacket.DebugPrintSubPacket();
+ ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
+ if (paramRequest.paramName.Equals("charaWork/exp"))
+ player.GetActor().SendCharaExpInfo();
+ break;
+ /* RECRUITMENT */
+ //Start Recruiting
+ case 0x01C3:
+ StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false));
+ break;
+ //End Recruiting
+ case 0x01C4:
+ client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false));
+ break;
+ //Party Window Opened, Request State
+ case 0x01C5:
+ client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(player.actorID, true, true, 1), true, false));
+ break;
+ //Search Recruiting
+ case 0x01C7:
+ RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data);
+ break;
+ //Get Recruitment Details
+ case 0x01C8:
+ RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data);
+ RecruitmentDetails details = new RecruitmentDetails();
+ details.recruiterName = "Localhost Character";
+ details.purposeId = 2;
+ details.locationId = 1;
+ details.subTaskId = 1;
+ details.comment = "This is a test details packet sent by the server. No implementation has been Created yet...";
+ details.num[0] = 1;
+ client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(player.actorID, details), true, false));
+ break;
+ //Accepted Recruiting
+ case 0x01C6:
+ subpacket.DebugPrintSubPacket();
+ break;
+ /* SOCIAL STUFF */
+ case 0x01C9:
+ AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(player.actorID, true, addBlackList.name), true, false));
+ break;
+ case 0x01CA:
+ AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(player.actorID, true, RemoveBlackList.name), true, false));
+ break;
+ case 0x01CB:
+ int offset1 = 0;
+ client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(player.actorID, new String[] { "Test" }, ref offset1), true, false));
+ break;
+ case 0x01CC:
+ AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(player.actorID, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false));
+ break;
+ case 0x01CD:
+ AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false));
+ break;
+ case 0x01CE:
+ int offset2 = 0;
+ client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(player.actorID, new Tuple[] { new Tuple(01, "Test2") }, ref offset2), true, false));
+ break;
+ case 0x01CF:
+ client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(player.actorID, null), true, false));
+ break;
+ /* SUPPORT DESK STUFF */
+ //Request for FAQ/Info List
+ case 0x01D0:
+ FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, new string[] { "Testing FAQ1", "Coded style!" }), true, false));
+ break;
+ //Request for body of a faq/info selection
+ case 0x01D1:
+ FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, "HERE IS A GIANT BODY. Nothing else to say!"), true, false));
+ break;
+ //Request issue list
+ case 0x01D2:
+ GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
+ client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false));
+ break;
+ //Request if GM ticket exists
+ case 0x01D3:
+ client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, false), true, false));
+ break;
+ //Request for GM response message
+ case 0x01D4:
+ client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false));
+ break;
+ //GM Ticket Sent
+ case 0x01D5:
+ GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
+ Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
+ client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, true), true, false));
+ break;
+ //Request to end ticket
+ case 0x01D6:
+ client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false));
+ break;
+ default:
+ Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
+ subpacket.DebugPrintSubPacket();
+ break;
}
- else
- packet.DebugPrintPacket();
- }
+
}
}
diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs
index ca939e63..f8b4ece3 100644
--- a/FFXIVClassic Map Server/Server.cs
+++ b/FFXIVClassic Map Server/Server.cs
@@ -26,7 +26,7 @@ namespace FFXIVClassic_Map_Server
private Socket mServerSocket;
private Dictionary mConnectedPlayerList = new Dictionary();
- private List mConnectionList = new List();
+ private ZoneConnection mWorldConnection = new ZoneConnection();
private LuaEngine mLuaEngine = new LuaEngine();
private static WorldManager mWorldManager;
@@ -119,7 +119,7 @@ namespace FFXIVClassic_Map_Server
Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
Console.ForegroundColor = ConsoleColor.Gray;
- mProcessor = new PacketProcessor(this, mConnectedPlayerList, mConnectionList);
+ mProcessor = new PacketProcessor(this, mConnectedPlayerList);
//mGameThread = new Thread(new ThreadStart(mProcessor.update));
//mGameThread.Start();
@@ -138,21 +138,18 @@ namespace FFXIVClassic_Map_Server
#region Socket Handling
private void AcceptCallback(IAsyncResult result)
{
- ClientConnection conn = null;
+ ZoneConnection conn = null;
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
try
{
- conn = new ClientConnection();
+ conn = new ZoneConnection();
conn.socket = socket.EndAccept(result);
conn.buffer = new byte[BUFFER_SIZE];
- lock (mConnectionList)
- {
- mConnectionList.Add(conn);
- }
-
+ mWorldConnection = conn;
+
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port);
//Queue recieving of data from the connection
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
@@ -163,11 +160,7 @@ namespace FFXIVClassic_Map_Server
{
if (conn != null)
{
-
- lock (mConnectionList)
- {
- mConnectionList.Remove(conn);
- }
+ mWorldConnection = null;
}
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
}
@@ -175,10 +168,7 @@ namespace FFXIVClassic_Map_Server
{
if (conn != null)
{
- lock (mConnectionList)
- {
- mConnectionList.Remove(conn);
- }
+ mWorldConnection = null;
}
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
}
@@ -208,20 +198,13 @@ namespace FFXIVClassic_Map_Server
///
private void ReceiveCallback(IAsyncResult result)
{
- ClientConnection conn = (ClientConnection)result.AsyncState;
+ ZoneConnection conn = (ZoneConnection)result.AsyncState;
//Check if disconnected
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
{
- if (mConnectedPlayerList.ContainsKey(conn.owner))
- mConnectedPlayerList.Remove(conn.owner);
- lock (mConnectionList)
- {
- mConnectionList.Remove(conn);
- }
- if (conn.connType == BasePacket.TYPE_ZONE)
- Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
- return;
+ mWorldConnection = null;
+ Program.Log.Info("Disconnected from world server!");
}
try
@@ -237,13 +220,13 @@ namespace FFXIVClassic_Map_Server
//Build packets until can no longer or out of data
while (true)
{
- BasePacket basePacket = BuildPacket(ref offset, conn.buffer, bytesRead);
+ SubPacket subPacket = SubPacket.CreatePacket(ref offset, conn.buffer, bytesRead);
//If can't build packet, break, else process another
- if (basePacket == null)
+ if (subPacket == null)
break;
else
- mProcessor.ProcessPacket(conn, basePacket);
+ mProcessor.ProcessPacket(conn, subPacket);
}
//Not all bytes consumed, transfer leftover to beginning
@@ -264,63 +247,20 @@ namespace FFXIVClassic_Map_Server
}
else
{
- Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
-
- lock (mConnectionList)
- {
- mConnectionList.Remove(conn);
- }
+ mWorldConnection = null;
+ Program.Log.Info("Disconnected from world server!");
}
}
catch (SocketException)
{
if (conn.socket != null)
{
- Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
-
- lock (mConnectionList)
- {
- mConnectionList.Remove(conn);
- }
+ mWorldConnection = null;
+ Program.Log.Info("Disconnected from world server!");
}
}
}
- ///
- /// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
- ///
- /// Current offset in buffer.
- /// Incoming buffer.
- /// Returns either a BasePacket or null if not enough data.
- public BasePacket BuildPacket(ref int offset, byte[] buffer, int bytesRead)
- {
- BasePacket newPacket = null;
-
- //Too small to even get length
- if (bytesRead <= offset)
- return null;
-
- ushort packetSize = BitConverter.ToUInt16(buffer, offset);
-
- //Too small to whole packet
- if (bytesRead < offset + packetSize)
- return null;
-
- if (buffer.Length < offset + packetSize)
- return null;
-
- try
- {
- newPacket = new BasePacket(buffer, ref offset);
- }
- catch (OverflowException)
- {
- return null;
- }
-
- return newPacket;
- }
-
#endregion
diff --git a/FFXIVClassic Map Server/ClientConnection.cs b/FFXIVClassic Map Server/ZoneConnection.cs
similarity index 72%
rename from FFXIVClassic Map Server/ClientConnection.cs
rename to FFXIVClassic Map Server/ZoneConnection.cs
index fcae92c6..4a1af12d 100644
--- a/FFXIVClassic Map Server/ClientConnection.cs
+++ b/FFXIVClassic Map Server/ZoneConnection.cs
@@ -7,27 +7,22 @@ using System.Net;
namespace FFXIVClassic_Map_Server
{
- class ClientConnection
+ class ZoneConnection
{
//Connection stuff
- public Blowfish blowfish;
public Socket socket;
public byte[] buffer;
- private BlockingCollection SendPacketQueue = new BlockingCollection(1000);
+ private BlockingCollection SendPacketQueue = new BlockingCollection(1000);
public int lastPartialSize = 0;
- //Instance Stuff
- public uint owner = 0;
- public int connType = 0;
-
public void QueuePacket(BasePacket packet)
{
- SendPacketQueue.Add(packet);
+ //SendPacketQueue.Add(packet);
}
public void QueuePacket(SubPacket subpacket, bool isAuthed, bool isEncrypted)
{
- SendPacketQueue.Add(BasePacket.CreatePacket(subpacket, isAuthed, isEncrypted));
+ SendPacketQueue.Add(subpacket);
}
public void FlushQueuedSendPackets()
@@ -37,9 +32,9 @@ namespace FFXIVClassic_Map_Server
while (SendPacketQueue.Count > 0)
{
- BasePacket packet = SendPacketQueue.Take();
+ SubPacket packet = SendPacketQueue.Take();
- byte[] packetBytes = packet.GetPacketBytes();
+ byte[] packetBytes = packet.GetBytes();
try
{
diff --git a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
index 052bec4e..17addb4b 100644
--- a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
+++ b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs
@@ -20,50 +20,20 @@ namespace FFXIVClassic_Map_Server.dataobjects
public uint languageCode = 1;
- private ClientConnection zoneConnection;
- private ClientConnection chatConnection;
+ private ZoneConnection zoneConnection;
private uint lastPingPacket = Utils.UnixTimeStampUTC();
public string errorMessage = "";
- public ConnectedPlayer(uint actorId)
+ public ConnectedPlayer(ZoneConnection zc, uint actorId)
{
+ zoneConnection = zc;
this.actorID = actorId;
playerActor = new Player(this, actorId);
actorInstanceList.Add(playerActor);
}
- public void SetConnection(int type, ClientConnection conn)
- {
- conn.connType = type;
- switch (type)
- {
- case BasePacket.TYPE_ZONE:
- zoneConnection = conn;
- break;
- case BasePacket.TYPE_CHAT:
- chatConnection = conn;
- break;
- }
- }
-
- public bool IsClientConnectionsReady()
- {
- return (zoneConnection != null && chatConnection != null);
- }
-
- public void Disconnect()
- {
- zoneConnection.Disconnect();
- chatConnection.Disconnect();
- }
-
- public bool IsDisconnected()
- {
- return (!zoneConnection.IsConnected() && !chatConnection.IsConnected());
- }
-
public void QueuePacket(BasePacket basePacket)
{
zoneConnection.QueuePacket(basePacket);
diff --git a/FFXIVClassic World Server/ConfigConstants.cs b/FFXIVClassic World Server/ConfigConstants.cs
index 028ad36a..7f8b29aa 100644
--- a/FFXIVClassic World Server/ConfigConstants.cs
+++ b/FFXIVClassic World Server/ConfigConstants.cs
@@ -18,15 +18,15 @@ namespace FFXIVClassic_World_Server
public static bool Load()
{
- Program.Log.Info("Loading config.ini");
+ Program.Log.Info("Loading world_config.ini");
- if (!File.Exists("./config.ini"))
+ if (!File.Exists("./world_config.ini"))
{
Program.Log.Error("FILE NOT FOUND!");
return false;
}
- INIFile configIni = new INIFile("./config.ini");
+ INIFile configIni = new INIFile("./world_config.ini");
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1");
ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "54992");
diff --git a/FFXIVClassic World Server/DataObjects/ZoneServer.cs b/FFXIVClassic World Server/DataObjects/ZoneServer.cs
index b3cf09e1..e7371402 100644
--- a/FFXIVClassic World Server/DataObjects/ZoneServer.cs
+++ b/FFXIVClassic World Server/DataObjects/ZoneServer.cs
@@ -16,6 +16,9 @@ namespace FFXIVClassic_World_Server.DataObjects
public readonly int[] ownedZoneIds;
public bool isConnected = false;
public Socket zoneServerConnection;
+ private ClientConnection conn;
+
+ private byte[] buffer = new byte[0xFFFF];
public ZoneServer(string ip, int port)
{
@@ -34,6 +37,18 @@ namespace FFXIVClassic_World_Server.DataObjects
{
zoneServerConnection.Connect(remoteEP);
isConnected = true;
+ conn = new ClientConnection();
+ conn.socket = zoneServerConnection;
+ conn.buffer = new byte[0xFFFF];
+
+ try
+ {
+ zoneServerConnection.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
+ }
+ catch (Exception e)
+ {
+ throw new ApplicationException("Error occured starting listeners, check inner exception", e);
+ }
}
catch (Exception e)
{ Program.Log.Error("Failed to connect"); return; }
@@ -54,5 +69,71 @@ namespace FFXIVClassic_World_Server.DataObjects
}
}
+ private void ReceiveCallback(IAsyncResult result)
+ {
+ ClientConnection conn = (ClientConnection)result.AsyncState;
+ //Check if disconnected
+ if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
+ {
+ conn = null;
+ isConnected = false;
+ Program.Log.Info("Zone server @ {0}:{1} disconnected!", zoneServerIp, zoneServerPort);
+ return;
+ }
+
+ try
+ {
+ int bytesRead = conn.socket.EndReceive(result);
+
+ bytesRead += conn.lastPartialSize;
+
+ if (bytesRead >= 0)
+ {
+ int offset = 0;
+
+ //Build packets until can no longer or out of data
+ while (true)
+ {
+ SubPacket subpacket = SubPacket.CreatePacket(ref offset, conn.buffer, bytesRead);
+
+ //If can't build packet, break, else process another
+ if (subpacket == null)
+ break;
+ else
+ Server.GetServer().OnReceiveSubPacketFromZone(this, subpacket);
+ }
+
+ //Not all bytes consumed, transfer leftover to beginning
+ if (offset < bytesRead)
+ Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset);
+
+ conn.lastPartialSize = bytesRead - offset;
+
+ //Build any queued subpackets into basepackets and send
+ conn.FlushQueuedSendPackets();
+
+ if (offset < bytesRead)
+ //Need offset since not all bytes consumed
+ conn.socket.BeginReceive(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset), SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
+ else
+ //All bytes consumed, full buffer available
+ conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
+ }
+ else
+ {
+ conn = null;
+ isConnected = false;
+ Program.Log.Info("Zone server @ {0}:{1} disconnected!", zoneServerIp, zoneServerPort);
+ }
+ }
+ catch (SocketException)
+ {
+ conn = null;
+ isConnected = false;
+ Program.Log.Info("Zone server @ {0}:{1} disconnected!", zoneServerIp, zoneServerPort);
+ }
+ }
+
+
}
}
diff --git a/FFXIVClassic World Server/NLog.config b/FFXIVClassic World Server/NLog.config
index aea50410..e3e21f9c 100644
--- a/FFXIVClassic World Server/NLog.config
+++ b/FFXIVClassic World Server/NLog.config
@@ -53,6 +53,7 @@
+