1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-21 20:27:47 +00:00

Merge branch 'proxy_server' into develop

# Conflicts:
#	FFXIVClassic Common Class Lib/packages.config
This commit is contained in:
Filip Maj 2016-12-03 14:03:13 -05:00
commit 3864bf6d85
195 changed files with 5926 additions and 1601 deletions

View file

@ -3,11 +3,11 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using FFXIVClassic.Common;
using NLog; using NLog;
using NLog.Targets; using NLog.Targets;
using Ionic.Zlib;
namespace FFXIVClassic_Map_Server.packets namespace FFXIVClassic.Common
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct BasePacketHeader public struct BasePacketHeader
@ -295,6 +295,41 @@ namespace FFXIVClassic_Map_Server.packets
return packet; return packet;
} }
/// <summary>
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
/// </summary>
/// <param name="offset">Current offset in buffer.</param>
/// <param name="buffer">Incoming buffer.</param>
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
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) public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet)
{ {
var data = packet.data; var data = packet.data;
@ -347,6 +382,28 @@ namespace FFXIVClassic_Map_Server.packets
} }
} }
public static unsafe void DecompressPacket(ref BasePacket packet)
{
using (var compressedStream = new MemoryStream(packet.data))
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
packet.data = resultStream.ToArray();
}
}
public static unsafe void CompressPacket(ref BasePacket packet)
{
using (var compressedStream = new MemoryStream(packet.data))
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Compress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
packet.data = resultStream.ToArray();
}
}
#endregion #endregion
} }

View file

@ -38,6 +38,9 @@
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="DotNetZip">
<HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL"> <Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath> <HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -56,12 +59,14 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BasePacket.cs" />
<Compile Include="Bitfield.cs" /> <Compile Include="Bitfield.cs" />
<Compile Include="Blowfish.cs" /> <Compile Include="Blowfish.cs" />
<Compile Include="EfficientHashTables.cs" /> <Compile Include="EfficientHashTables.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sql.cs" /> <Compile Include="Sql.cs" />
<Compile Include="STA_INIFile.cs" /> <Compile Include="STA_INIFile.cs" />
<Compile Include="SubPacket.cs" />
<Compile Include="Utils.cs" /> <Compile Include="Utils.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -4,7 +4,7 @@ using FFXIVClassic.Common;
using NLog; using NLog;
using NLog.Targets; using NLog.Targets;
namespace FFXIVClassic_Lobby_Server.packets namespace FFXIVClassic.Common
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct SubPacketHeader public struct SubPacketHeader
@ -72,26 +72,38 @@ namespace FFXIVClassic_Lobby_Server.packets
offset += header.subpacketSize; offset += header.subpacketSize;
} }
public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data) public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data) : this(true, opcode, sourceId, targetId, data) { }
public SubPacket(bool isGameMessage, ushort opcode, uint sourceId, uint targetId, byte[] data)
{ {
header = new SubPacketHeader(); header = new SubPacketHeader();
if (isGameMessage)
{
gameMessage = new GameMessageHeader(); gameMessage = new GameMessageHeader();
gameMessage.opcode = opcode; gameMessage.opcode = opcode;
header.sourceId = sourceId;
header.targetId = targetId;
gameMessage.timestamp = Utils.UnixTimeStampUTC(); gameMessage.timestamp = Utils.UnixTimeStampUTC();
header.type = 0x03;
header.unknown1 = 0x00;
gameMessage.unknown4 = 0x14; gameMessage.unknown4 = 0x14;
gameMessage.unknown5 = 0x00; gameMessage.unknown5 = 0x00;
gameMessage.unknown6 = 0x00; gameMessage.unknown6 = 0x00;
}
header.sourceId = sourceId;
header.targetId = targetId;
if (isGameMessage)
header.type = 0x03;
else
header.type = opcode;
header.unknown1 = 0x00;
this.data = data; this.data = data;
header.subpacketSize = (ushort) (SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length); header.subpacketSize = (ushort) (SUBPACKET_SIZE + data.Length);
if (isGameMessage)
header.subpacketSize += GAMEMESSAGE_SIZE;
} }
public SubPacket(SubPacket original, uint newTargetId) public SubPacket(SubPacket original, uint newTargetId)
@ -141,6 +153,41 @@ namespace FFXIVClassic_Lobby_Server.packets
return outBytes; return outBytes;
} }
/// <summary>
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
/// </summary>
/// <param name="offset">Current offset in buffer.</param>
/// <param name="buffer">Incoming buffer.</param>
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
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() public void DebugPrintSubPacket()
{ {
#if DEBUG #if DEBUG
@ -157,6 +204,9 @@ namespace FFXIVClassic_Lobby_Server.packets
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE), logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
ConsoleOutputColor.DarkMagenta); ConsoleOutputColor.DarkMagenta);
} }
else
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE),
ConsoleOutputColor.DarkMagenta);
#endif #endif
} }
} }

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Microsoft.Net.Compilers" version="2.0.0-beta3" targetFramework="net45" developmentDependency="true" /> <package id="DotNetZip" version="1.10.1" targetFramework="net45" />
<package id="MySql.Data" version="6.9.8" targetFramework="net45" /> <package id="MySql.Data" version="6.9.8" targetFramework="net45" />
<package id="NLog" version="4.3.5" targetFramework="net45" /> <package id="NLog" version="4.3.5" targetFramework="net45" />
</packages> </packages>

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Net.Sockets; using System.Net.Sockets;
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Cyotek.Collections.Generic; using Cyotek.Collections.Generic;

View file

@ -91,7 +91,6 @@
<Compile Include="Database.cs" /> <Compile Include="Database.cs" />
<Compile Include="dataobjects\World.cs" /> <Compile Include="dataobjects\World.cs" />
<Compile Include="PacketProcessor.cs" /> <Compile Include="PacketProcessor.cs" />
<Compile Include="packets\BasePacket.cs" />
<Compile Include="packets\receive\CharacterModifyPacket.cs" /> <Compile Include="packets\receive\CharacterModifyPacket.cs" />
<Compile Include="packets\receive\SecurityHandshakePacket.cs" /> <Compile Include="packets\receive\SecurityHandshakePacket.cs" />
<Compile Include="packets\receive\SelectCharacterPacket.cs" /> <Compile Include="packets\receive\SelectCharacterPacket.cs" />
@ -101,7 +100,6 @@
<Compile Include="packets\send\ErrorPacket.cs" /> <Compile Include="packets\send\ErrorPacket.cs" />
<Compile Include="packets\HardCoded_Packets.cs" /> <Compile Include="packets\HardCoded_Packets.cs" />
<Compile Include="packets\send\SelectCharacterConfirmPacket.cs" /> <Compile Include="packets\send\SelectCharacterConfirmPacket.cs" />
<Compile Include="packets\SubPacket.cs" />
<Compile Include="packets\send\CharacterListPacket.cs" /> <Compile Include="packets\send\CharacterListPacket.cs" />
<Compile Include="packets\send\ImportListPacket.cs" /> <Compile Include="packets\send\ImportListPacket.cs" />
<Compile Include="packets\send\AccountListPacket.cs" /> <Compile Include="packets\send\AccountListPacket.cs" />

View file

@ -38,13 +38,13 @@
<target xsi:type="ColoredConsole" name="packets" <target xsi:type="ColoredConsole" name="packets"
layout="${message}"> layout="${message}">
<highlight-row <highlight-row
condition="equals('${logger}', 'FFXIVClassic_Lobby_Server.packets.BasePacket') and equals('${event-context:item=color}', '6')" condition="equals('${logger}', 'FFXIVClassic.Common.BasePacket') and equals('${event-context:item=color}', '6')"
backgroundColor="DarkYellow" foregroundColor="NoChange" /> backgroundColor="DarkYellow" foregroundColor="NoChange" />
<highlight-row <highlight-row
condition="equals('${logger}', 'FFXIVClassic_Lobby_Server.packets.SubPacket') and equals('${event-context:item=color}', '4')" condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '4')"
backgroundColor="DarkRed" foregroundColor="NoChange" /> backgroundColor="DarkRed" foregroundColor="NoChange" />
<highlight-row <highlight-row
condition="equals('${logger}', 'FFXIVClassic_Lobby_Server.packets.SubPacket') and equals('${event-context:item=color}', '5')" condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '5')"
backgroundColor="DarkMagenta" foregroundColor="NoChange" /> backgroundColor="DarkMagenta" foregroundColor="NoChange" />
</target> </target>
</targets> </targets>

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using NLog; using NLog;

View file

@ -1,361 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using FFXIVClassic.Common;
using NLog;
using NLog.Targets;
namespace FFXIVClassic_Lobby_Server.packets
{
[StructLayout(LayoutKind.Sequential)]
public struct BasePacketHeader
{
public byte isAuthenticated;
public byte isEncrypted;
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;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public byte[] data;
public BasePacketHeader header;
//Loads a sniffed packet from a file
public unsafe BasePacket(string path)
{
var bytes = File.ReadAllBytes(path);
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
if (bytes.Length < header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
int packetSize = header.packetSize;
if (packetSize - BASEPACKET_SIZE != 0)
{
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
}
else
data = new byte[0];
}
//Loads a sniffed packet from a byte array
public unsafe BasePacket(byte[] bytes)
{
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
if (bytes.Length < header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
int packetSize = header.packetSize;
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
}
public unsafe BasePacket(byte[] bytes, ref int offset)
{
if (bytes.Length < offset + BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[offset])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
int packetSize = header.packetSize;
if (bytes.Length < offset + header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, offset + BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
offset += packetSize;
}
public BasePacket(BasePacketHeader header, byte[] data)
{
this.header = header;
this.data = data;
}
public List<SubPacket> GetSubpackets()
{
var subpackets = new List<SubPacket>(header.numSubpackets);
var offset = 0;
while (offset < data.Length)
subpackets.Add(new SubPacket(data, ref offset));
return subpackets;
}
public static unsafe BasePacketHeader GetHeader(byte[] bytes)
{
BasePacketHeader header;
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
return header;
}
public byte[] GetHeaderBytes()
{
var size = Marshal.SizeOf(header);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] GetPacketBytes()
{
var outBytes = new byte[header.packetSize];
Array.Copy(GetHeaderBytes(), 0, outBytes, 0, BASEPACKET_SIZE);
Array.Copy(data, 0, outBytes, BASEPACKET_SIZE, data.Length);
return outBytes;
}
//Replaces all instances of the sniffed actorID with the given one
public void ReplaceActorID(uint actorID)
{
using (var mem = new MemoryStream(data))
{
using (var binWriter = new BinaryWriter(mem))
{
using (var binreader = new BinaryReader(mem))
{
while (binreader.BaseStream.Position + 4 < data.Length)
{
var read = binreader.ReadUInt32();
if (read == 0x029B2941 || read == 0x02977DC7 || read == 0x0297D2C8 || read == 0x0230d573 ||
read == 0x23317df || read == 0x23344a3 || read == 0x1730bdb) //Original ID
{
binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin);
binWriter.Write(actorID);
}
}
}
}
}
}
//Replaces all instances of the sniffed actorID with the given one
public void ReplaceActorID(uint fromActorID, uint actorID)
{
using (var mem = new MemoryStream(data))
{
using (var binWriter = new BinaryWriter(mem))
{
using (var binreader = new BinaryReader(mem))
{
while (binreader.BaseStream.Position + 4 < data.Length)
{
var read = binreader.ReadUInt32();
if (read == fromActorID) //Original ID
{
binWriter.BaseStream.Seek(binreader.BaseStream.Position - 0x4, SeekOrigin.Begin);
binWriter.Write(actorID);
}
}
}
}
}
}
public void DebugPrintPacket()
{
#if DEBUG
logger.ColorDebug(
string.Format("IsAuth:{0} Size:0x{1:X}, NumSubpackets:{2}{3}{4}",
header.isAuthenticated, header.packetSize, header.numSubpackets,
Environment.NewLine, Utils.ByteArrayToHex(GetHeaderBytes())), ConsoleOutputColor.DarkYellow);
foreach (var sub in GetSubpackets())
{
sub.DebugPrintSubPacket();
}
#endif
}
#region Utility Functions
public static BasePacket CreatePacket(List<SubPacket> subpackets, bool isAuthed, bool isEncrypted)
{
//Create Header
var header = new BasePacketHeader();
byte[] data = null;
header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0;
header.isEncrypted = isEncrypted ? (byte) 1 : (byte) 0;
header.numSubpackets = (ushort) subpackets.Count;
header.packetSize = BASEPACKET_SIZE;
header.timestamp = Utils.MilisUnixTimeStampUTC();
//Get packet size
foreach (var subpacket in subpackets)
header.packetSize += subpacket.header.subpacketSize;
data = new byte[header.packetSize - 0x10];
//Add Subpackets
var offset = 0;
foreach (var subpacket in subpackets)
{
var subpacketData = subpacket.GetBytes();
Array.Copy(subpacketData, 0, data, offset, subpacketData.Length);
offset += (ushort) subpacketData.Length;
}
Debug.Assert(data != null && offset == data.Length && header.packetSize == 0x10 + offset);
var packet = new BasePacket(header, data);
return packet;
}
public static BasePacket CreatePacket(SubPacket subpacket, bool isAuthed, bool isEncrypted)
{
//Create Header
var header = new BasePacketHeader();
byte[] data = null;
header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0;
header.isEncrypted = isEncrypted ? (byte) 1 : (byte) 0;
header.numSubpackets = 1;
header.packetSize = BASEPACKET_SIZE;
header.timestamp = Utils.MilisUnixTimeStampUTC();
//Get packet size
header.packetSize += subpacket.header.subpacketSize;
data = new byte[header.packetSize - 0x10];
//Add Subpackets
var subpacketData = subpacket.GetBytes();
Array.Copy(subpacketData, 0, data, 0, subpacketData.Length);
Debug.Assert(data != null);
var packet = new BasePacket(header, data);
return packet;
}
public static BasePacket CreatePacket(byte[] data, bool isAuthed, bool isEncrypted)
{
Debug.Assert(data != null);
//Create Header
var header = new BasePacketHeader();
header.isAuthenticated = isAuthed ? (byte) 1 : (byte) 0;
header.isEncrypted = isEncrypted ? (byte) 1 : (byte) 0;
header.numSubpackets = 1;
header.packetSize = BASEPACKET_SIZE;
header.timestamp = Utils.MilisUnixTimeStampUTC();
//Get packet size
header.packetSize += (ushort) data.Length;
var packet = new BasePacket(header, data);
return packet;
}
public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet)
{
var data = packet.data;
int size = packet.header.packetSize;
var offset = 0;
while (offset < data.Length)
{
if (data.Length < offset + SubPacket.SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
SubPacketHeader header;
fixed (byte* pdata = &data[offset])
{
header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (data.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
blowfish.Encipher(data, offset + 0x10, header.subpacketSize - 0x10);
offset += header.subpacketSize;
}
}
public static unsafe void DecryptPacket(Blowfish blowfish, ref BasePacket packet)
{
var data = packet.data;
int size = packet.header.packetSize;
var offset = 0;
while (offset < data.Length)
{
if (data.Length < offset + SubPacket.SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
SubPacketHeader header;
fixed (byte* pdata = &data[offset])
{
header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (data.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
blowfish.Decipher(data, offset + 0x10, header.subpacketSize - 0x10);
offset += header.subpacketSize;
}
}
#endregion
}
public static class LoggerExtensions
{
public static void ColorDebug(this Logger logger, string message, ConsoleOutputColor color)
{
var logEvent = new LogEventInfo(LogLevel.Debug, logger.Name, message);
logEvent.Properties["color"] = (int) color;
logger.Log(logEvent);
}
}
}

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic.Common;
using FFXIVClassic_Lobby_Server.dataobjects;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using System.Text; using System.Text;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic.Common;
using FFXIVClassic_Lobby_Server.dataobjects;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using System.Text; using System.Text;

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Lobby_Server.dataobjects; using FFXIVClassic.Common;
using FFXIVClassic_Lobby_Server.dataobjects;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View file

@ -1,40 +1,25 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets;
using System.IO; using System.IO;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server;
using FFXIVClassic_Map_Server.packets.send; using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.actors.chara.player; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.Properties;
namespace FFXIVClassic_Map_Server namespace FFXIVClassic_Map_Server
{ {
class CommandProcessor class CommandProcessor
{ {
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList;
private static Dictionary<uint, Item> gamedataItems = Server.GetGamedataItems(); private static Dictionary<uint, Item> gamedataItems = Server.GetGamedataItems();
// For the moment, this is the only predefined item // For the moment, this is the only predefined item
// TODO: make a list/enum in the future so that items can be given by name, instead of by id // TODO: make a list/enum in the future so that items can be given by name, instead of by id
const UInt32 ITEM_GIL = 1000001; const UInt32 ITEM_GIL = 1000001;
public CommandProcessor(Dictionary<uint, ConnectedPlayer> playerList)
{
mConnectedPlayerList = playerList;
}
public void ChangeProperty(uint id, uint value, string target) public void ChangeProperty(uint id, uint value, string target)
{ {
SetActorPropetyPacket ChangeProperty = new SetActorPropetyPacket(target); SetActorPropetyPacket ChangeProperty = new SetActorPropetyPacket(target);
@ -43,9 +28,11 @@ namespace FFXIVClassic_Map_Server
ChangeProperty.AddInt(id, value); ChangeProperty.AddInt(id, value);
ChangeProperty.AddTarget(); ChangeProperty.AddTarget();
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList) Dictionary<uint, Session> sessionList = Server.GetServer().GetSessionList();
foreach (KeyValuePair<uint, Session> entry in sessionList)
{ {
SubPacket ChangePropertyPacket = ChangeProperty.BuildPacket((entry.Value.actorID), (entry.Value.actorID)); SubPacket ChangePropertyPacket = ChangeProperty.BuildPacket((entry.Value.id), (entry.Value.id));
BasePacket packet = BasePacket.CreatePacket(ChangePropertyPacket, true, false); BasePacket packet = BasePacket.CreatePacket(ChangePropertyPacket, true, false);
packet.DebugPrintPacket(); packet.DebugPrintPacket();
@ -60,13 +47,13 @@ namespace FFXIVClassic_Map_Server
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="message"></param> /// <param name="message"></param>
private void SendMessage(ConnectedPlayer client, String message) private void SendMessage(Session session, String message)
{ {
if (client != null) if (session != null)
client.GetActor().QueuePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message)); session.GetActor().QueuePacket(SendMessagePacket.BuildPacket(session.id, session.id, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message));
} }
internal bool DoCommand(string input, ConnectedPlayer client) internal bool DoCommand(string input, Session session)
{ {
if (!input.Any() || input.Equals("")) if (!input.Any() || input.Equals(""))
return false; return false;
@ -88,7 +75,9 @@ namespace FFXIVClassic_Map_Server
if (cmd.Any()) if (cmd.Any())
{ {
// if client isnt null, take player to be the player actor // if client isnt null, take player to be the player actor
var player = client?.GetActor(); Player player = null;
if (session != null)
player = session.GetActor();
if (cmd.Equals("help")) if (cmd.Equals("help"))
{ {
@ -125,11 +114,11 @@ namespace FFXIVClassic_Map_Server
if (split[0].Equals("reloaditems")) if (split[0].Equals("reloaditems"))
{ {
Program.Log.Info(String.Format("Got request to reload item gamedata")); Program.Log.Info(String.Format("Got request to reload item gamedata"));
SendMessage(client, "Reloading Item Gamedata..."); SendMessage(session, "Reloading Item Gamedata...");
gamedataItems.Clear(); gamedataItems.Clear();
gamedataItems = Database.GetItemGamedata(); gamedataItems = Database.GetItemGamedata();
Program.Log.Info(String.Format("Loaded {0} items.", gamedataItems.Count)); Program.Log.Info(String.Format("Loaded {0} items.", gamedataItems.Count));
SendMessage(client, String.Format("Loaded {0} items.", gamedataItems.Count)); SendMessage(session, String.Format("Loaded {0} items.", gamedataItems.Count));
return true; return true;
} }
#endregion #endregion

View file

@ -30,7 +30,7 @@ namespace FFXIVClassic_Map_Server
INIFile configIni = new INIFile("./map_config.ini"); INIFile configIni = new INIFile("./map_config.ini");
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1"); 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.OPTIONS_TIMESTAMP = configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true");
ConfigConstants.DATABASE_WORLDID = UInt32.Parse(configIni.GetValue("Database", "worldid", "0")); ConfigConstants.DATABASE_WORLDID = UInt32.Parse(configIni.GetValue("Database", "worldid", "0"));

View file

@ -5,7 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.utils; using FFXIVClassic_Map_Server.utils;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.packets.send.player; using FFXIVClassic_Map_Server.packets.send.player;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
@ -258,6 +258,8 @@ namespace FFXIVClassic_Map_Server
positionY = @y, positionY = @y,
positionZ = @z, positionZ = @z,
rotation = @rot, rotation = @rot,
destinationZoneId = @destZone,
destinationSpawnType = @destSpawn,
currentZoneId = @zoneId currentZoneId = @zoneId
WHERE id = @charaId WHERE id = @charaId
"; ";
@ -269,6 +271,8 @@ namespace FFXIVClassic_Map_Server
cmd.Parameters.AddWithValue("@z", player.positionZ); cmd.Parameters.AddWithValue("@z", player.positionZ);
cmd.Parameters.AddWithValue("@rot", player.rotation); cmd.Parameters.AddWithValue("@rot", player.rotation);
cmd.Parameters.AddWithValue("@zoneId", player.zoneId); cmd.Parameters.AddWithValue("@zoneId", player.zoneId);
cmd.Parameters.AddWithValue("@destZone", player.destinationZone);
cmd.Parameters.AddWithValue("@destSpawn", player.destinationSpawnType);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -402,7 +406,9 @@ namespace FFXIVClassic_Map_Server
tribe, tribe,
restBonus, restBonus,
achievementPoints, achievementPoints,
playTime playTime,
destinationZoneId,
destinationSpawnType
FROM characters WHERE id = @charId"; FROM characters WHERE id = @charId";
cmd = new MySqlCommand(query, conn); cmd = new MySqlCommand(query, conn);
@ -420,7 +426,6 @@ namespace FFXIVClassic_Map_Server
player.currentMainState = reader.GetUInt16(5); player.currentMainState = reader.GetUInt16(5);
player.zoneId = reader.GetUInt32(6); player.zoneId = reader.GetUInt32(6);
player.isZoning = true; player.isZoning = true;
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
player.gcCurrent = reader.GetByte(7); player.gcCurrent = reader.GetByte(7);
player.gcRankLimsa = reader.GetByte(8); player.gcRankLimsa = reader.GetByte(8);
player.gcRankGridania = reader.GetByte(9); player.gcRankGridania = reader.GetByte(9);
@ -434,6 +439,13 @@ namespace FFXIVClassic_Map_Server
player.playerWork.restBonusExpRate = reader.GetInt32(17); player.playerWork.restBonusExpRate = reader.GetInt32(17);
player.achievementPoints = reader.GetUInt32(18); player.achievementPoints = reader.GetUInt32(18);
player.playTime = reader.GetUInt32(19); player.playTime = reader.GetUInt32(19);
player.destinationZone = reader.GetUInt32("destinationZoneId");
player.destinationSpawnType = reader.GetByte("destinationSpawnType");
if (player.destinationZone != 0)
player.zoneId = player.destinationZone;
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
} }
} }

View file

@ -93,7 +93,7 @@
<Compile Include="actors\quest\Quest.cs" /> <Compile Include="actors\quest\Quest.cs" />
<Compile Include="actors\StaticActors.cs" /> <Compile Include="actors\StaticActors.cs" />
<Compile Include="actors\world\WorldMaster.cs" /> <Compile Include="actors\world\WorldMaster.cs" />
<Compile Include="ClientConnection.cs" /> <Compile Include="dataobjects\ZoneConnection.cs" />
<Compile Include="CommandProcessor.cs" /> <Compile Include="CommandProcessor.cs" />
<Compile Include="ConfigConstants.cs" /> <Compile Include="ConfigConstants.cs" />
<Compile Include="Database.cs" /> <Compile Include="Database.cs" />
@ -112,7 +112,7 @@
<Compile Include="actors\chara\player\PlayerWork.cs" /> <Compile Include="actors\chara\player\PlayerWork.cs" />
<Compile Include="dataobjects\DBWorld.cs" /> <Compile Include="dataobjects\DBWorld.cs" />
<Compile Include="dataobjects\InventoryItem.cs" /> <Compile Include="dataobjects\InventoryItem.cs" />
<Compile Include="dataobjects\ConnectedPlayer.cs" /> <Compile Include="dataobjects\Session.cs" />
<Compile Include="dataobjects\Item.cs" /> <Compile Include="dataobjects\Item.cs" />
<Compile Include="dataobjects\RecruitmentDetails.cs" /> <Compile Include="dataobjects\RecruitmentDetails.cs" />
<Compile Include="dataobjects\SeamlessBoundry.cs" /> <Compile Include="dataobjects\SeamlessBoundry.cs" />
@ -124,7 +124,6 @@
<Compile Include="lua\LuaPlayer.cs" /> <Compile Include="lua\LuaPlayer.cs" />
<Compile Include="lua\LuaScript.cs" /> <Compile Include="lua\LuaScript.cs" />
<Compile Include="PacketProcessor.cs" /> <Compile Include="PacketProcessor.cs" />
<Compile Include="packets\BasePacket.cs" />
<Compile Include="packets\receive\ChatMessagePacket.cs" /> <Compile Include="packets\receive\ChatMessagePacket.cs" />
<Compile Include="packets\receive\events\EventUpdatePacket.cs" /> <Compile Include="packets\receive\events\EventUpdatePacket.cs" />
<Compile Include="packets\receive\events\EventStartPacket.cs" /> <Compile Include="packets\receive\events\EventStartPacket.cs" />
@ -258,9 +257,13 @@
<Compile Include="packets\send\_0x02Packet.cs" /> <Compile Include="packets\send\_0x02Packet.cs" />
<Compile Include="packets\send\_0x10Packet.cs" /> <Compile Include="packets\send\_0x10Packet.cs" />
<Compile Include="packets\send\_0xE2Packet.cs" /> <Compile Include="packets\send\_0xE2Packet.cs" />
<Compile Include="packets\SubPacket.cs" />
<Compile Include="packets\receive\PingPacket.cs" /> <Compile Include="packets\receive\PingPacket.cs" />
<Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" /> <Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\ErrorPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\SessionEndPacket.cs" />
<Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" />
<Compile Include="packets\WorldPackets\Send\SessionBeginConfirmPacket.cs" />
<Compile Include="packets\WorldPackets\Send\SessionEndConfirmPacket.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="lua\LuaUtils.cs" /> <Compile Include="lua\LuaUtils.cs" />
@ -286,6 +289,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<None Include="packages.config" /> <None Include="packages.config" />
<Compile Include="packets\WorldPackets\Send\WorldRequestZoneChangePacket.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">

View file

@ -38,13 +38,13 @@
<target xsi:type="ColoredConsole" name="packets" <target xsi:type="ColoredConsole" name="packets"
layout="${message}"> layout="${message}">
<highlight-row <highlight-row
condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.BasePacket') and equals('${event-context:item=color}', '6')" condition="equals('${logger}', 'FFXIVClassic.Common.BasePacket') and equals('${event-context:item=color}', '6')"
backgroundColor="DarkYellow" foregroundColor="NoChange" /> backgroundColor="DarkYellow" foregroundColor="NoChange" />
<highlight-row <highlight-row
condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.SubPacket') and equals('${event-context:item=color}', '4')" condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '4')"
backgroundColor="DarkRed" foregroundColor="NoChange" /> backgroundColor="DarkRed" foregroundColor="NoChange" />
<highlight-row <highlight-row
condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.SubPacket') and equals('${event-context:item=color}', '5')" condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '5')"
backgroundColor="DarkMagenta" foregroundColor="NoChange" /> backgroundColor="DarkMagenta" foregroundColor="NoChange" />
</target> </target>
</targets> </targets>
@ -55,6 +55,7 @@
<logger name='FFXIVClassic_Map_Server.Program' minlevel='Trace' writeTo='console' /> <logger name='FFXIVClassic_Map_Server.Program' minlevel='Trace' writeTo='console' />
<logger name='FFXIVClassic_Map_Server.lua.*' minlevel='Trace' writeTo='console' /> <logger name='FFXIVClassic_Map_Server.lua.*' minlevel='Trace' writeTo='console' />
<logger name='FFXIVClassic_Map_Server.packets.*' minlevel='Debug' writeTo='packets' /> <logger name='FFXIVClassic_Map_Server.packets.*' minlevel='Debug' writeTo='packets' />
<logger name='FFXIVClassic.Common.*' minlevel='Debug' writeTo='packets' />
<!-- <!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f" Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" /> <logger name="*" minlevel="Debug" writeTo="f" />

View file

@ -1,5 +1,5 @@
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -18,165 +18,86 @@ using FFXIVClassic_Map_Server.packets.send.recruitment;
using FFXIVClassic_Map_Server.packets.receive.events; using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
using FFXIVClassic_Map_Server.packets.WorldPackets.Receive;
namespace FFXIVClassic_Map_Server namespace FFXIVClassic_Map_Server
{ {
class PacketProcessor class PacketProcessor
{ {
Server mServer; Server mServer;
CommandProcessor cp;
Dictionary<uint, ConnectedPlayer> mPlayers;
List<ClientConnection> mConnections;
public PacketProcessor(Server server, Dictionary<uint, ConnectedPlayer> playerList, List<ClientConnection> connectionList) public PacketProcessor(Server server)
{ {
mPlayers = playerList;
mConnections = connectionList;
mServer = server; 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) Session session = mServer.GetSession(subpacket.header.targetId);
BasePacket.DecryptPacket(client.blowfish, ref packet);
List<SubPacket> subPackets = packet.GetSubpackets(); if (session == null && subpacket.gameMessage.opcode != 0x1000)
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
};
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)
{
//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)
{
ConnectedPlayer player = null;
if(mPlayers.ContainsKey(client.owner))
player = mPlayers[client.owner];
if (player == null || !player.IsClientConnectionsReady())
return; return;
//Normal Game Opcode //Normal Game Opcode
switch (subpacket.gameMessage.opcode) switch (subpacket.gameMessage.opcode)
{ {
//World Server - Error
case 0x100A:
ErrorPacket worldError = new ErrorPacket(subpacket.data);
switch (worldError.errorCode)
{
case 0x01:
session.GetActor().SendGameMessage(Server.GetWorldManager().GetActor(), 60005, 0x20);
break;
}
break;
//World Server - Session Begin
case 0x1000:
subpacket.DebugPrintSubPacket();
session = mServer.AddSession(subpacket.header.targetId);
if (session.GetActor().destinationZone != 0)
Server.GetWorldManager().DoZoneIn(session.GetActor(), false, session.GetActor().destinationSpawnType);
Program.Log.Info("{0} has been added to the session list.", session.GetActor().customDisplayName);
client.FlushQueuedSendPackets();
break;
//World Server - Session End
case 0x1001:
SessionEndPacket endSessionPacket = new SessionEndPacket(subpacket.data);
if (endSessionPacket.destinationZoneId == 0)
session.GetActor().CleanupAndSave();
else
session.GetActor().CleanupAndSave(endSessionPacket.destinationZoneId, endSessionPacket.destinationSpawnType, endSessionPacket.destinationX, endSessionPacket.destinationY, endSessionPacket.destinationZ, endSessionPacket.destinationRot);
Server.GetServer().RemoveSession(session.id);
Program.Log.Info("{0} has been removed from the session list.", session.GetActor().customDisplayName);
client.QueuePacket(SessionEndConfirmPacket.BuildPacket(session, endSessionPacket.destinationZoneId), true, false);
client.FlushQueuedSendPackets();
break;
//Ping //Ping
case 0x0001: case 0x0001:
//subpacket.DebugPrintSubPacket(); //subpacket.DebugPrintSubPacket();
PingPacket pingPacket = new PingPacket(subpacket.data); PingPacket pingPacket = new PingPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(player.actorID, pingPacket.time), true, false)); client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(session.id, pingPacket.time), true, false));
player.Ping(); session.Ping();
break; break;
//Unknown //Unknown
case 0x0002: case 0x0002:
subpacket.DebugPrintSubPacket(); subpacket.DebugPrintSubPacket();
client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false); session = mServer.AddSession(subpacket.header.targetId);
client.QueuePacket(_0x2Packet.BuildPacket(session.id), true, false);
Server.GetWorldManager().DoLogin(player.GetActor()); LuaEngine.OnBeginLogin(session.GetActor());
Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1);
LuaEngine.OnLogin(session.GetActor());
client.FlushQueuedSendPackets();
break; break;
//Chat Received //Chat Received
@ -187,17 +108,17 @@ namespace FFXIVClassic_Map_Server
if (chatMessage.message.StartsWith("!")) if (chatMessage.message.StartsWith("!"))
{ {
if (cp.DoCommand(chatMessage.message, player)) if (Server.GetCommandProcessor().DoCommand(chatMessage.message, session))
continue; return; ;
} }
player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false); session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false);
break; break;
//Langauge Code //Langauge Code
case 0x0006: case 0x0006:
LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data); LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
player.languageCode = langCode.languageCode; session.languageCode = langCode.languageCode;
break; break;
//Unknown - Happens a lot at login, then once every time player zones //Unknown - Happens a lot at login, then once every time player zones
case 0x0007: case 0x0007:
@ -207,13 +128,12 @@ namespace FFXIVClassic_Map_Server
//Update Position //Update Position
case 0x00CA: case 0x00CA:
//Update Position //Update Position
//subpacket.DebugPrintSubPacket();
UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
player.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); session.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
player.GetActor().SendInstanceUpdate(); session.GetActor().SendInstanceUpdate();
if (player.GetActor().IsInZoneChange()) if (session.GetActor().IsInZoneChange())
player.GetActor().SetZoneChanging(false); session.GetActor().SetZoneChanging(false);
break; break;
//Set Target //Set Target
@ -221,13 +141,13 @@ namespace FFXIVClassic_Map_Server
//subpacket.DebugPrintSubPacket(); //subpacket.DebugPrintSubPacket();
SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
player.GetActor().currentTarget = setTarget.actorID; session.GetActor().currentTarget = setTarget.actorID;
player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true); session.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(session.id, session.id, setTarget.actorID), true);
break; break;
//Lock Target //Lock Target
case 0x00CC: case 0x00CC:
LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
player.GetActor().currentLockedTarget = lockTarget.actorID; session.GetActor().currentLockedTarget = lockTarget.actorID;
break; break;
//Start Event //Start Event
case 0x012D: case 0x012D:
@ -250,19 +170,19 @@ namespace FFXIVClassic_Map_Server
Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID); Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID; session.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
player.GetActor().currentEventName = eventStart.triggerName; session.GetActor().currentEventName = eventStart.triggerName;
if (ownerActor == null) if (ownerActor == null)
{ {
//Is it a instance actor? //Is it a instance actor?
ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner); ownerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
if (ownerActor == null) if (ownerActor == null)
{ {
//Is it a Director? //Is it a Director?
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId) if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
ownerActor = player.GetActor().currentDirector; ownerActor = session.GetActor().currentDirector;
else 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)); 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));
@ -271,7 +191,7 @@ namespace FFXIVClassic_Map_Server
} }
} }
player.GetActor().StartEvent(ownerActor, eventStart); session.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)); 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; break;
@ -285,42 +205,42 @@ namespace FFXIVClassic_Map_Server
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)); 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 //Is it a static actor? If not look in the player's instance
Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner); Actor updateOwnerActor = Server.GetStaticActors(session.GetActor().currentEventOwner);
if (updateOwnerActor == null) if (updateOwnerActor == null)
{ {
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner); updateOwnerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId) if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
updateOwnerActor = player.GetActor().currentDirector; updateOwnerActor = session.GetActor().currentDirector;
if (updateOwnerActor == null) if (updateOwnerActor == null)
break; break;
} }
*/ */
player.GetActor().UpdateEvent(eventUpdate); session.GetActor().UpdateEvent(eventUpdate);
//LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate); //LuaEngine.DoActorOnEventUpdated(session.GetActor(), updateOwnerActor, eventUpdate);
break; break;
case 0x012F: case 0x012F:
//subpacket.DebugPrintSubPacket(); //subpacket.DebugPrintSubPacket();
ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data); ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
if (paramRequest.paramName.Equals("charaWork/exp")) if (paramRequest.paramName.Equals("charaWork/exp"))
player.GetActor().SendCharaExpInfo(); session.GetActor().SendCharaExpInfo();
break; break;
/* RECRUITMENT */ /* RECRUITMENT */
//Start Recruiting //Start Recruiting
case 0x01C3: case 0x01C3:
StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data); StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false)); client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(session.id, true), true, false));
break; break;
//End Recruiting //End Recruiting
case 0x01C4: case 0x01C4:
client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false)); client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(session.id), true, false));
break; break;
//Party Window Opened, Request State //Party Window Opened, Request State
case 0x01C5: case 0x01C5:
client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(player.actorID, true, true, 1), true, false)); client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(session.id, true, true, 1), true, false));
break; break;
//Search Recruiting //Search Recruiting
case 0x01C7: case 0x01C7:
@ -336,7 +256,7 @@ namespace FFXIVClassic_Map_Server
details.subTaskId = 1; details.subTaskId = 1;
details.comment = "This is a test details packet sent by the server. No implementation has been Created yet..."; details.comment = "This is a test details packet sent by the server. No implementation has been Created yet...";
details.num[0] = 1; details.num[0] = 1;
client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(player.actorID, details), true, false)); client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(session.id, details), true, false));
break; break;
//Accepted Recruiting //Accepted Recruiting
case 0x01C6: case 0x01C6:
@ -345,74 +265,71 @@ namespace FFXIVClassic_Map_Server
/* SOCIAL STUFF */ /* SOCIAL STUFF */
case 0x01C9: case 0x01C9:
AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data); AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(player.actorID, true, addBlackList.name), true, false)); client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(session.id, true, addBlackList.name), true, false));
break; break;
case 0x01CA: case 0x01CA:
AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data); AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(player.actorID, true, RemoveBlackList.name), true, false)); client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(session.id, true, RemoveBlackList.name), true, false));
break; break;
case 0x01CB: case 0x01CB:
int offset1 = 0; int offset1 = 0;
client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(player.actorID, new String[] { "Test" }, ref offset1), true, false)); client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(session.id, new String[] { "Test" }, ref offset1), true, false));
break; break;
case 0x01CC: case 0x01CC:
AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data); AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(player.actorID, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false)); client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(session.id, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false));
break; break;
case 0x01CD: case 0x01CD:
AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data); AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false)); client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(session.id, true, RemoveFriendList.name), true, false));
break; break;
case 0x01CE: case 0x01CE:
int offset2 = 0; int offset2 = 0;
client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(player.actorID, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2), true, false)); client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(session.id, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2), true, false));
break; break;
case 0x01CF: case 0x01CF:
client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(player.actorID, null), true, false)); client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(session.id, null), true, false));
break; break;
/* SUPPORT DESK STUFF */ /* SUPPORT DESK STUFF */
//Request for FAQ/Info List //Request for FAQ/Info List
case 0x01D0: case 0x01D0:
FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data); FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, new string[] { "Testing FAQ1", "Coded style!" }), true, false)); client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(session.id, new string[] { "Testing FAQ1", "Coded style!" }), true, false));
break; break;
//Request for body of a faq/info selection //Request for body of a faq/info selection
case 0x01D1: case 0x01D1:
FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data); 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)); client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(session.id, "HERE IS A GIANT BODY. Nothing else to say!"), true, false));
break; break;
//Request issue list //Request issue list
case 0x01D2: case 0x01D2:
GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data); GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false)); client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(session.id, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false));
break; break;
//Request if GM ticket exists //Request if GM ticket exists
case 0x01D3: case 0x01D3:
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, false), true, false)); client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(session.id, false), true, false));
break; break;
//Request for GM response message //Request for GM response message
case 0x01D4: case 0x01D4:
client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false)); client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(session.id, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false));
break; break;
//GM Ticket Sent //GM Ticket Sent
case 0x01D5: case 0x01D5:
GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data); GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody); Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, true), true, false)); client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(session.id, true), true, false));
break; break;
//Request to end ticket //Request to end ticket
case 0x01D6: case 0x01D6:
client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false)); client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(session.id), true, false));
break; break;
default: default:
Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode); Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
subpacket.DebugPrintSubPacket(); subpacket.DebugPrintSubPacket();
break; break;
} }
}
else
packet.DebugPrintPacket();
}
} }
} }

View file

@ -63,14 +63,14 @@ namespace FFXIVClassic_Map_Server
if (startServer) if (startServer)
{ {
Server server = new Server(); Server server = new Server();
CommandProcessor cp = new CommandProcessor(server.GetConnectedPlayerList());
server.StartServer(); server.StartServer();
while (startServer) while (startServer)
{ {
String input = Console.ReadLine(); String input = Console.ReadLine();
Log.Info("[Console Input] " + input); Log.Info("[Console Input] " + input);
cp.DoCommand(input, null); Server.GetCommandProcessor().DoCommand(input, null);
} }
} }

View file

@ -2,11 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using NLog;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
@ -17,7 +15,6 @@ namespace FFXIVClassic_Map_Server
public const int FFXIV_MAP_PORT = 54992; public const int FFXIV_MAP_PORT = 54992;
public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF
public const int BACKLOG = 100; public const int BACKLOG = 100;
public const int HEALTH_THREAD_SLEEP_TIME = 5;
public const string STATIC_ACTORS_PATH = "./staticactors.bin"; public const string STATIC_ACTORS_PATH = "./staticactors.bin";
@ -25,60 +22,28 @@ namespace FFXIVClassic_Map_Server
private Socket mServerSocket; private Socket mServerSocket;
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint, ConnectedPlayer>(); private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
private LuaEngine mLuaEngine = new LuaEngine(); private LuaEngine mLuaEngine = new LuaEngine();
private static CommandProcessor mCommandProcessor = new CommandProcessor();
private static ZoneConnection mWorldConnection = new ZoneConnection();
private static WorldManager mWorldManager; private static WorldManager mWorldManager;
private static Dictionary<uint, Item> gamedataItems; private static Dictionary<uint, Item> mGamedataItems;
private static StaticActors mStaticActors; private static StaticActors mStaticActors;
private PacketProcessor mProcessor; private PacketProcessor mProcessor;
private Thread mConnectionHealthThread;
private bool killHealthThread = false;
private void ConnectionHealth()
{
Program.Log.Info("Connection Health thread started; it will run every {0} seconds.", HEALTH_THREAD_SLEEP_TIME);
while (!killHealthThread)
{
lock (mConnectedPlayerList)
{
List<ConnectedPlayer> dcedPlayers = new List<ConnectedPlayer>();
foreach (ConnectedPlayer cp in mConnectedPlayerList.Values)
{
if (cp.CheckIfDCing())
dcedPlayers.Add(cp);
}
foreach (ConnectedPlayer cp in dcedPlayers)
cp.GetActor().CleanupAndSave();
}
Thread.Sleep(HEALTH_THREAD_SLEEP_TIME * 1000);
}
}
public Server() public Server()
{ {
mSelf = this; mSelf = this;
} }
public static Server GetServer()
{
return mSelf;
}
public bool StartServer() public bool StartServer()
{ {
mConnectionHealthThread = new Thread(new ThreadStart(ConnectionHealth));
mConnectionHealthThread.Name = "MapThread:Health";
//mConnectionHealthThread.Start();
mStaticActors = new StaticActors(STATIC_ACTORS_PATH); mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
gamedataItems = Database.GetItemGamedata(); mGamedataItems = Database.GetItemGamedata();
Program.Log.Info("Loaded {0} items.", gamedataItems.Count); Program.Log.Info("Loaded {0} items.", mGamedataItems.Count);
mWorldManager = new WorldManager(this); mWorldManager = new WorldManager(this);
mWorldManager.LoadZoneList(); mWorldManager.LoadZoneList();
@ -88,11 +53,11 @@ namespace FFXIVClassic_Map_Server
mWorldManager.LoadSpawnLocations(); mWorldManager.LoadSpawnLocations();
mWorldManager.SpawnAllActors(); mWorldManager.SpawnAllActors();
IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT)); IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT));
try try
{ {
mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); mServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
} }
catch (Exception e) catch (Exception e)
{ {
@ -120,39 +85,72 @@ namespace FFXIVClassic_Map_Server
Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port); Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
mProcessor = new PacketProcessor(this, mConnectedPlayerList, mConnectionList); mProcessor = new PacketProcessor(this);
//mGameThread = new Thread(new ThreadStart(mProcessor.update)); //mGameThread = new Thread(new ThreadStart(mProcessor.update));
//mGameThread.Start(); //mGameThread.Start();
return true; return true;
} }
public void RemovePlayer(Player player) #region Session Handling
public Session AddSession(uint id)
{ {
lock (mConnectedPlayerList) if (mSessionList.ContainsKey(id))
return mSessionList[id];
Session session = new Session(id);
mSessionList.Add(id, session);
return session;
}
public void RemoveSession(uint id)
{ {
if (mConnectedPlayerList.ContainsKey(player.actorId)) if (mSessionList.ContainsKey(id))
mConnectedPlayerList.Remove(player.actorId); {
mSessionList.Remove(id);
} }
} }
public Session GetSession(uint id)
{
if (mSessionList.ContainsKey(id))
return mSessionList[id];
else
return null;
}
public Session GetSession(string name)
{
foreach (Session s in mSessionList.Values)
{
if (s.GetActor().customDisplayName.ToLower().Equals(name.ToLower()))
return s;
}
return null;
}
public Dictionary<uint, Session> GetSessionList()
{
return mSessionList;
}
#endregion
#region Socket Handling #region Socket Handling
private void AcceptCallback(IAsyncResult result) private void AcceptCallback(IAsyncResult result)
{ {
ClientConnection conn = null; ZoneConnection conn = null;
Socket socket = (System.Net.Sockets.Socket)result.AsyncState; Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
try try
{ {
conn = new ClientConnection(); conn = new ZoneConnection();
conn.socket = socket.EndAccept(result); conn.socket = socket.EndAccept(result);
conn.buffer = new byte[BUFFER_SIZE]; conn.buffer = new byte[BUFFER_SIZE];
lock (mConnectionList) mWorldConnection = conn;
{
mConnectionList.Add(conn);
}
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port); 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 //Queue recieving of data from the connection
@ -164,11 +162,7 @@ namespace FFXIVClassic_Map_Server
{ {
if (conn != null) if (conn != null)
{ {
mWorldConnection = null;
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
} }
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket); mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
} }
@ -176,53 +170,25 @@ namespace FFXIVClassic_Map_Server
{ {
if (conn != null) if (conn != null)
{ {
lock (mConnectionList) mWorldConnection = null;
{
mConnectionList.Remove(conn);
}
} }
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket); mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
} }
} }
public static Actor GetStaticActors(uint id)
{
return mStaticActors.GetActor(id);
}
public static Actor GetStaticActors(string name)
{
return mStaticActors.FindStaticActor(name);
}
public static Item GetItemGamedata(uint id)
{
if (gamedataItems.ContainsKey(id))
return gamedataItems[id];
else
return null;
}
/// <summary> /// <summary>
/// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend. /// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend.
/// </summary> /// </summary>
/// <param name="result"></param> /// <param name="result"></param>
private void ReceiveCallback(IAsyncResult result) private void ReceiveCallback(IAsyncResult result)
{ {
ClientConnection conn = (ClientConnection)result.AsyncState; ZoneConnection conn = (ZoneConnection)result.AsyncState;
//Check if disconnected //Check if disconnected
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0)) if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
{ {
if (mConnectedPlayerList.ContainsKey(conn.owner)) mWorldConnection = null;
mConnectedPlayerList.Remove(conn.owner); Program.Log.Info("Disconnected from world server!");
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;
} }
try try
@ -238,13 +204,13 @@ namespace FFXIVClassic_Map_Server
//Build packets until can no longer or out of data //Build packets until can no longer or out of data
while (true) 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 can't build packet, break, else process another
if (basePacket == null) if (subPacket == null)
break; break;
else else
mProcessor.ProcessPacket(conn, basePacket); mProcessor.ProcessPacket(conn, subPacket);
} }
//Not all bytes consumed, transfer leftover to beginning //Not all bytes consumed, transfer leftover to beginning
@ -265,79 +231,63 @@ namespace FFXIVClassic_Map_Server
} }
else else
{ {
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner); mWorldConnection = null;
Program.Log.Info("Disconnected from world server!");
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
} }
} }
catch (SocketException) catch (SocketException)
{ {
if (conn.socket != null) if (conn.socket != null)
{ {
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner); mWorldConnection = null;
Program.Log.Info("Disconnected from world server!");
lock (mConnectionList)
{
mConnectionList.Remove(conn);
} }
} }
} }
}
/// <summary>
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
/// </summary>
/// <param name="offset">Current offset in buffer.</param>
/// <param name="buffer">Incoming buffer.</param>
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
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 #endregion
public static ZoneConnection GetWorldConnection()
{
return mWorldConnection;
}
public static Server GetServer()
{
return mSelf;
}
public static CommandProcessor GetCommandProcessor()
{
return mCommandProcessor;
}
public static WorldManager GetWorldManager() public static WorldManager GetWorldManager()
{ {
return mWorldManager; return mWorldManager;
} }
public Dictionary<uint, ConnectedPlayer> GetConnectedPlayerList()
{
return mConnectedPlayerList;
}
public static Dictionary<uint, Item> GetGamedataItems() public static Dictionary<uint, Item> GetGamedataItems()
{ {
return gamedataItems; return mGamedataItems;
}
public static Actor GetStaticActors(uint id)
{
return mStaticActors.GetActor(id);
}
public static Actor GetStaticActors(string name)
{
return mStaticActors.FindStaticActor(name);
}
public static Item GetItemGamedata(uint id)
{
if (mGamedataItems.ContainsKey(id))
return mGamedataItems[id];
else
return null;
} }
} }

View file

@ -62,10 +62,13 @@ namespace FFXIVClassic_Map_Server
canStealth, canStealth,
isInstanceRaid isInstanceRaid
FROM server_zones FROM server_zones
WHERE zoneName IS NOT NULL"; WHERE zoneName IS NOT NULL and serverIp = @ip and serverPort = @port";
MySqlCommand cmd = new MySqlCommand(query, conn); MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@ip", ConfigConstants.OPTIONS_BINDIP);
cmd.Parameters.AddWithValue("@port", ConfigConstants.OPTIONS_PORT);
using (MySqlDataReader reader = cmd.ExecuteReader()) using (MySqlDataReader reader = cmd.ExecuteReader())
{ {
while (reader.Read()) while (reader.Read())
@ -334,13 +337,20 @@ namespace FFXIVClassic_Map_Server
{ {
while (reader.Read()) while (reader.Read())
{ {
uint zoneId = reader.GetUInt32("zoneId");
uint classId = reader.GetUInt32("actorClassId");
if (!actorClasses.ContainsKey(classId))
continue;
if (!zoneList.ContainsKey(zoneId))
continue;
Zone zone = zoneList[zoneId];
if (zone == null)
continue;
string customName = null; string customName = null;
if (!reader.IsDBNull(11)) if (!reader.IsDBNull(11))
customName = reader.GetString("customDisplayName"); customName = reader.GetString("customDisplayName");
uint classId = reader.GetUInt32("actorClassId");
string uniqueId = reader.GetString("uniqueId"); string uniqueId = reader.GetString("uniqueId");
uint zoneId = reader.GetUInt32("zoneId");
string privAreaName = reader.GetString("privateAreaName"); string privAreaName = reader.GetString("privateAreaName");
uint privAreaLevel = reader.GetUInt32("privateAreaLevel"); uint privAreaLevel = reader.GetUInt32("privateAreaLevel");
float x = reader.GetFloat("positionX"); float x = reader.GetFloat("positionX");
@ -350,15 +360,6 @@ namespace FFXIVClassic_Map_Server
ushort state = reader.GetUInt16("actorState"); ushort state = reader.GetUInt16("actorState");
uint animId = reader.GetUInt32("animationId"); uint animId = reader.GetUInt32("animationId");
if (!actorClasses.ContainsKey(classId))
continue;
if (!zoneList.ContainsKey(zoneId))
continue;
Zone zone = zoneList[zoneId];
if (zone == null)
continue;
SpawnLocation spawn = new SpawnLocation(classId, uniqueId, zoneId, privAreaName, privAreaLevel, x, y, z, rot, state, animId); SpawnLocation spawn = new SpawnLocation(classId, uniqueId, zoneId, privAreaName, privAreaLevel, x, y, z, rot, state, animId);
zone.AddSpawnLocation(spawn); zone.AddSpawnLocation(spawn);
@ -524,13 +525,6 @@ namespace FFXIVClassic_Map_Server
//Moves actor to new zone, and sends packets to spawn at the given coords. //Moves actor to new zone, and sends packets to spawn at the given coords.
public void DoZoneChange(Player player, uint destinationZoneId, string destinationPrivateArea, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation) public void DoZoneChange(Player player, uint destinationZoneId, string destinationPrivateArea, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{ {
Area oldZone = player.zone;
//Remove player from currentZone if transfer else it's login
if (player.zone != null)
{
oldZone.RemoveActorFromZone(player);
}
//Add player to new zone and update //Add player to new zone and update
Area newArea; Area newArea;
@ -542,15 +536,16 @@ namespace FFXIVClassic_Map_Server
//This server does not contain that zoneId //This server does not contain that zoneId
if (newArea == null) if (newArea == null)
{ {
if (oldZone != null) Program.Log.Debug("Request to change to zone not on this server by: {0}.", player.customDisplayName);
{ RequestWorldServerZoneChange(player, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation);
oldZone.AddActorToZone(player); return;
} }
var message = "WorldManager.DoZoneChange: unable to change areas, new area is not valid."; Area oldZone = player.zone;
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM, "[Debug]", message); //Remove player from currentZone if transfer else it's login
Program.Log.Debug(message); if (player.zone != null)
return; {
oldZone.RemoveActorFromZone(player);
} }
newArea.AddActorToZone(player); newArea.AddActorToZone(player);
@ -613,8 +608,8 @@ namespace FFXIVClassic_Map_Server
} }
} }
//Login Zone In //Session started, zone into world
public void DoLogin(Player player) public void DoZoneIn(Player player, bool isLogin, ushort spawnType)
{ {
//Add player to new zone and update //Add player to new zone and update
Zone zone = GetZone(player.zoneId); Zone zone = GetZone(player.zoneId);
@ -626,14 +621,24 @@ namespace FFXIVClassic_Map_Server
//Set the current zone and add player //Set the current zone and add player
player.zone = zone; player.zone = zone;
LuaEngine.OnBeginLogin(player);
zone.AddActorToZone(player); zone.AddActorToZone(player);
//Send packets //Send packets
player.SendZoneInPackets(this, 0x1); if (!isLogin)
{
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId), true, false);
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x2), true, false);
player.SendZoneInPackets(this, spawnType);
}
player.SendZoneInPackets(this, spawnType);
player.destinationZone = 0;
player.destinationSpawnType = 0;
Database.SavePlayerPosition(player);
player.playerSession.LockUpdates(false);
LuaEngine.OnLogin(player);
LuaEngine.OnZoneIn(player); LuaEngine.OnZoneIn(player);
} }
@ -648,6 +653,12 @@ namespace FFXIVClassic_Map_Server
} }
private void RequestWorldServerZoneChange(Player player, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{
ZoneConnection zc = Server.GetWorldConnection();
zc.RequestZoneChange(player.playerSession.id, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation);
}
public Player GetPCInWorld(string name) public Player GetPCInWorld(string name)
{ {
foreach (Zone zone in zoneList.Values) foreach (Zone zone in zoneList.Values)

View file

@ -1,4 +1,4 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic_Map_Server.actors; using FFXIVClassic_Map_Server.actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
@ -71,7 +71,7 @@ namespace FFXIVClassic_Map_Server.Actors
return SetActorSpeedPacket.BuildPacket(actorId, playerActorId); return SetActorSpeedPacket.BuildPacket(actorId, playerActorId);
} }
public SubPacket CreateSpawnPositonPacket(uint playerActorId, uint spawnType) public SubPacket CreateSpawnPositonPacket(uint playerActorId, ushort spawnType)
{ {
SubPacket spawnPacket; SubPacket spawnPacket;
if (!spawnedFirstTime && playerActorId == actorId) if (!spawnedFirstTime && playerActorId == actorId)
@ -92,7 +92,7 @@ namespace FFXIVClassic_Map_Server.Actors
return spawnPacket; return spawnPacket;
} }
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, uint spawnType) public SubPacket CreateSpawnTeleportPacket(uint playerActorId, ushort spawnType)
{ {
SubPacket spawnPacket; SubPacket spawnPacket;
@ -224,7 +224,7 @@ namespace FFXIVClassic_Map_Server.Actors
return GetSpawnPackets(playerActorId, 0x1); return GetSpawnPackets(playerActorId, 0x1);
} }
public virtual BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) public virtual BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{ {
List<SubPacket> subpackets = new List<SubPacket>(); List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId, 8)); subpackets.Add(CreateAddActorPacket(playerActorId, 8));

View file

@ -1,6 +1,6 @@
using FFXIVClassic_Map_Server; using FFXIVClassic_Map_Server;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.area; using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.npc; using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,6 +1,6 @@
using FFXIVClassic_Map_Server; using FFXIVClassic_Map_Server;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.chara.npc; using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors.Chara; using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
@ -35,6 +36,8 @@ namespace FFXIVClassic_Map_Server.Actors
public const int L_INDEXFINGER = 26; public const int L_INDEXFINGER = 26;
public const int UNKNOWN = 27; public const int UNKNOWN = 27;
public bool isStatic = false;
public uint modelId; public uint modelId;
public uint[] appearanceIds = new uint[28]; public uint[] appearanceIds = new uint[28];

View file

@ -4,7 +4,7 @@ using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.Actors.Chara; using FFXIVClassic_Map_Server.Actors.Chara;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.packets.receive.events; using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.utils; using FFXIVClassic_Map_Server.utils;
@ -88,11 +88,15 @@ namespace FFXIVClassic_Map_Server.Actors
Player player = Server.GetWorldManager().GetPCInWorld(playerActorId); Player player = Server.GetWorldManager().GetPCInWorld(playerActorId);
lParams = DoActorInit(player); lParams = DoActorInit(player);
if (lParams != null && lParams.Count >= 3 && lParams[2].typeID == 0 && (int)lParams[2].value == 0)
isStatic = true;
if (lParams == null) if (lParams == null)
{ {
string classPathFake = "/Chara/Npc/Populace/PopulaceStandard"; string classPathFake = "/Chara/Npc/Populace/PopulaceStandard";
string classNameFake = "PopulaceStandard"; string classNameFake = "PopulaceStandard";
lParams = LuaUtils.CreateLuaParamList(classPathFake, false, false, false, false, false, 0xF47F6, false, false, 0, 0); lParams = LuaUtils.CreateLuaParamList(classPathFake, false, false, false, false, false, 0xF47F6, false, false, 0, 0);
isStatic = true;
//ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams).DebugPrintSubPacket(); //ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams).DebugPrintSubPacket();
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams); return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams);
} }
@ -111,7 +115,7 @@ namespace FFXIVClassic_Map_Server.Actors
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
} }
public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{ {
List<SubPacket> subpackets = new List<SubPacket>(); List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId)); subpackets.Add(CreateAddActorPacket(playerActorId));

View file

@ -1,7 +1,6 @@
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.actor.inventory; using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
using System.Collections.Generic; using System.Collections.Generic;
namespace FFXIVClassic_Map_Server.actors.chara.player namespace FFXIVClassic_Map_Server.actors.chara.player

View file

@ -1,8 +1,8 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.actor.inventory; using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View file

@ -1,5 +1,5 @@
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.chara.player; using FFXIVClassic_Map_Server.actors.chara.player;
using FFXIVClassic_Map_Server.actors.director; using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
@ -7,8 +7,6 @@ using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send; using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.packets.send.actor.events;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
using FFXIVClassic_Map_Server.packets.send.events; using FFXIVClassic_Map_Server.packets.send.events;
using FFXIVClassic_Map_Server.packets.send.list; using FFXIVClassic_Map_Server.packets.send.list;
using FFXIVClassic_Map_Server.packets.send.player; using FFXIVClassic_Map_Server.packets.send.player;
@ -17,6 +15,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using MoonSharp.Interpreter; using MoonSharp.Interpreter;
using FFXIVClassic_Map_Server.packets.receive.events; using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
namespace FFXIVClassic_Map_Server.Actors namespace FFXIVClassic_Map_Server.Actors
{ {
@ -85,6 +84,8 @@ namespace FFXIVClassic_Map_Server.Actors
public Coroutine currentEventRunning; public Coroutine currentEventRunning;
//Player Info //Player Info
public uint destinationZone;
public ushort destinationSpawnType;
public uint[] timers = new uint[20]; public uint[] timers = new uint[20];
public ushort currentJob; public ushort currentJob;
public uint currentTitle; public uint currentTitle;
@ -124,9 +125,9 @@ namespace FFXIVClassic_Map_Server.Actors
public PlayerWork playerWork = new PlayerWork(); public PlayerWork playerWork = new PlayerWork();
public ConnectedPlayer playerSession; public Session playerSession;
public Player(ConnectedPlayer cp, uint actorID) : base(actorID) public Player(Session cp, uint actorID) : base(actorID)
{ {
playerSession = cp; playerSession = cp;
actorName = String.Format("_pc{0:00000000}", actorID); actorName = String.Format("_pc{0:00000000}", actorID);
@ -260,7 +261,7 @@ namespace FFXIVClassic_Map_Server.Actors
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams); return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
} }
public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType) public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{ {
List<SubPacket> subpackets = new List<SubPacket>(); List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId, 8)); subpackets.Add(CreateAddActorPacket(playerActorId, 8));
@ -481,7 +482,7 @@ namespace FFXIVClassic_Map_Server.Actors
QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId));
QueuePacket(GetSpawnPackets(actorId, spawnType)); QueuePacket(GetSpawnPackets(actorId, spawnType));
GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); //GetSpawnPackets(actorId, spawnType).DebugPrintPacket();
#region grouptest #region grouptest
//Retainers //Retainers
@ -654,15 +655,38 @@ namespace FFXIVClassic_Map_Server.Actors
public void CleanupAndSave() public void CleanupAndSave()
{ {
playerSession.LockUpdates(true);
//Remove actor from zone and main server list //Remove actor from zone and main server list
zone.RemoveActorFromZone(this); zone.RemoveActorFromZone(this);
Server.GetServer().RemovePlayer(this);
//Set Destination to 0
this.destinationZone = 0;
this.destinationSpawnType = 0;
//Save Player //Save Player
Database.SavePlayerPlayTime(this); Database.SavePlayerPlayTime(this);
Database.SavePlayerPosition(this); Database.SavePlayerPosition(this);
}
Program.Log.Info("{0} has been logged out and saved.", this.customDisplayName); public void CleanupAndSave(uint destinationZone, ushort spawnType, float destinationX, float destinationY, float destinationZ, float destinationRot)
{
playerSession.LockUpdates(true);
//Remove actor from zone and main server list
zone.RemoveActorFromZone(this);
//Set destination
this.destinationZone = destinationZone;
this.destinationSpawnType = spawnType;
this.positionX = destinationX;
this.positionY = destinationY;
this.positionZ = destinationZ;
this.rotation = destinationRot;
//Save Player
Database.SavePlayerPlayTime(this);
Database.SavePlayerPosition(this);
} }
public Area GetZone() public Area GetZone()
@ -731,7 +755,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendGameMessage(Actor sourceActor, Actor textIdOwner, ushort textId, byte log, params object[] msgParams) public void SendGameMessage(Actor sourceActor, Actor textIdOwner, ushort textId, byte log, params object[] msgParams)
{ {
if (msgParams.Length == 0) if (msgParams == null || msgParams.Length == 0)
{ {
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log)); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, sourceActor.actorId, textIdOwner.actorId, textId, log));
} }
@ -741,7 +765,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, params object[] msgParams) public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, params object[] msgParams)
{ {
if (msgParams.Length == 0) if (msgParams == null || msgParams.Length == 0)
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log)); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log));
else else
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams)));
@ -749,7 +773,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams) public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams)
{ {
if (msgParams.Length == 0) if (msgParams == null || msgParams.Length == 0)
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log)); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log));
else else
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams))); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams)));
@ -757,7 +781,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams) public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams)
{ {
if (msgParams.Length == 0) if (msgParams == null || msgParams.Length == 0)
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log)); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log));
else else
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams))); QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams)));

View file

@ -1,4 +1,4 @@
using FFXIVClassic_Map_Server.packets; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using System.Collections.Generic; using System.Collections.Generic;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors.director; using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,4 +1,5 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
using System.Collections.Generic; using System.Collections.Generic;

View file

@ -1,6 +1,6 @@
using FFXIVClassic_Map_Server; using FFXIVClassic_Map_Server;
using FFXIVClassic.Common; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor; using FFXIVClassic_Map_Server.packets.send.actor;
@ -12,66 +12,33 @@ using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.dataobjects namespace FFXIVClassic_Map_Server.dataobjects
{ {
class ConnectedPlayer class Session
{ {
public uint actorID = 0; public uint id = 0;
Player playerActor; Player playerActor;
public List<Actor> actorInstanceList = new List<Actor>(); public List<Actor> actorInstanceList = new List<Actor>();
public uint languageCode = 1; public uint languageCode = 1;
private ClientConnection zoneConnection;
private ClientConnection chatConnection;
private uint lastPingPacket = Utils.UnixTimeStampUTC(); private uint lastPingPacket = Utils.UnixTimeStampUTC();
public bool isUpdatesLocked = true;
public string errorMessage = ""; public string errorMessage = "";
public ConnectedPlayer(uint actorId) public Session(uint sessionId)
{ {
this.actorID = actorId; this.id = sessionId;
playerActor = new Player(this, actorId); playerActor = new Player(this, sessionId);
actorInstanceList.Add(playerActor); 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) public void QueuePacket(BasePacket basePacket)
{ {
zoneConnection.QueuePacket(basePacket); Server.GetWorldConnection().QueuePacket(basePacket);
} }
public void QueuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted) public void QueuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted)
{ {
zoneConnection.QueuePacket(subPacket, isAuthed, isEncrypted); Server.GetWorldConnection().QueuePacket(subPacket, isAuthed, isEncrypted);
} }
public Player GetActor() public Player GetActor()
@ -98,6 +65,9 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void UpdatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState) public void UpdatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState)
{ {
if (isUpdatesLocked)
return;
playerActor.oldPositionX = playerActor.positionX; playerActor.oldPositionX = playerActor.positionX;
playerActor.oldPositionY = playerActor.positionY; playerActor.oldPositionY = playerActor.positionY;
playerActor.oldPositionZ = playerActor.positionZ; playerActor.oldPositionZ = playerActor.positionZ;
@ -115,6 +85,9 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void UpdateInstance(List<Actor> list) public void UpdateInstance(List<Actor> list)
{ {
if (isUpdatesLocked)
return;
List<BasePacket> basePackets = new List<BasePacket>(); List<BasePacket> basePackets = new List<BasePacket>();
List<SubPacket> RemoveActorSubpackets = new List<SubPacket>(); List<SubPacket> RemoveActorSubpackets = new List<SubPacket>();
List<SubPacket> posUpdateSubpackets = new List<SubPacket>(); List<SubPacket> posUpdateSubpackets = new List<SubPacket>();
@ -139,6 +112,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
if (actorInstanceList.Contains(actor)) if (actorInstanceList.Contains(actor))
{ {
//Don't send for static characters (npcs)
if (actor is Character && ((Character)actor).isStatic)
continue;
GetActor().QueuePacket(actor.CreatePositionUpdatePacket(playerActor.actorId)); GetActor().QueuePacket(actor.CreatePositionUpdatePacket(playerActor.actorId));
} }
else else
@ -163,5 +140,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
actorInstanceList.Clear(); actorInstanceList.Clear();
} }
public void LockUpdates(bool f)
{
isUpdatesLocked = f;
}
} }
} }

View file

@ -0,0 +1,74 @@
using System;
using System.Net.Sockets;
using FFXIVClassic.Common;
using System.Collections.Concurrent;
using System.Net;
using System.Collections.Generic;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
namespace FFXIVClassic_Map_Server.dataobjects
{
class ZoneConnection
{
//Connection stuff
public Socket socket;
public byte[] buffer;
private BlockingCollection<SubPacket> SendPacketQueue = new BlockingCollection<SubPacket>(1000);
public int lastPartialSize = 0;
public void QueuePacket(BasePacket packet)
{
List<SubPacket> subPackets = packet.GetSubpackets();
foreach (SubPacket s in subPackets)
SendPacketQueue.Add(s);
}
public void QueuePacket(SubPacket subpacket, bool isAuthed, bool isEncrypted)
{
SendPacketQueue.Add(subpacket);
}
public void FlushQueuedSendPackets()
{
if (!socket.Connected)
return;
while (SendPacketQueue.Count > 0)
{
SubPacket packet = SendPacketQueue.Take();
byte[] packetBytes = packet.GetBytes();
try
{
socket.Send(packetBytes);
}
catch (Exception e)
{ Program.Log.Error("Weird case, socket was d/ced: {0}", e); }
}
}
public String GetAddress()
{
return String.Format("{0}:{1}", (socket.RemoteEndPoint as IPEndPoint).Address, (socket.RemoteEndPoint as IPEndPoint).Port);
}
public bool IsConnected()
{
return (socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
public void Disconnect()
{
if (socket.Connected)
socket.Disconnect(false);
}
public void RequestZoneChange(uint sessionId, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{
WorldRequestZoneChangePacket.BuildPacket(sessionId, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation).DebugPrintSubPacket();
QueuePacket(WorldRequestZoneChangePacket.BuildPacket(sessionId, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation), true, false);
}
}
}

View file

@ -1,4 +1,4 @@
using FFXIVClassic_Map_Server.packets; 
using FFXIVClassic_Map_Server.actors.director; using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using FFXIVClassic_Map_Server.lua; using FFXIVClassic_Map_Server.lua;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.lua namespace FFXIVClassic_Map_Server.lua
{ {

View file

@ -1,163 +0,0 @@
using System;
using System.Runtime.InteropServices;
using FFXIVClassic.Common;
using NLog;
using NLog.Targets;
namespace FFXIVClassic_Map_Server.packets
{
[StructLayout(LayoutKind.Sequential)]
public struct SubPacketHeader
{
public ushort subpacketSize;
public ushort type;
public uint sourceId;
public uint targetId;
public uint unknown1;
}
[StructLayout(LayoutKind.Sequential)]
public struct GameMessageHeader
{
public ushort unknown4; //Always 0x14
public ushort opcode;
public uint unknown5;
public uint timestamp;
public uint unknown6;
}
public class SubPacket
{
public const int SUBPACKET_SIZE = 0x10;
public const int GAMEMESSAGE_SIZE = 0x10;
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public byte[] data;
public GameMessageHeader gameMessage;
public SubPacketHeader header;
public unsafe SubPacket(byte[] bytes, ref int offset)
{
if (bytes.Length < offset + SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
fixed (byte* pdata = &bytes[offset])
{
header = (SubPacketHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (header.type == 0x3)
{
fixed (byte* pdata = &bytes[offset + SUBPACKET_SIZE])
{
gameMessage =
(GameMessageHeader) Marshal.PtrToStructure(new IntPtr(pdata), typeof(GameMessageHeader));
}
}
if (bytes.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
if (header.type == 0x3)
{
data = new byte[header.subpacketSize - SUBPACKET_SIZE - GAMEMESSAGE_SIZE];
Array.Copy(bytes, offset + SUBPACKET_SIZE + GAMEMESSAGE_SIZE, data, 0, data.Length);
}
else
{
data = new byte[header.subpacketSize - SUBPACKET_SIZE];
Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length);
}
offset += header.subpacketSize;
}
public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data)
{
header = new SubPacketHeader();
gameMessage = new GameMessageHeader();
gameMessage.opcode = opcode;
header.sourceId = sourceId;
header.targetId = targetId;
gameMessage.timestamp = Utils.UnixTimeStampUTC();
header.type = 0x03;
header.unknown1 = 0x00;
gameMessage.unknown4 = 0x14;
gameMessage.unknown5 = 0x00;
gameMessage.unknown6 = 0x00;
this.data = data;
header.subpacketSize = (ushort) (SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length);
}
public SubPacket(SubPacket original, uint newTargetId)
{
header = new SubPacketHeader();
gameMessage = original.gameMessage;
header.subpacketSize = original.header.subpacketSize;
header.type = original.header.type;
header.sourceId = original.header.sourceId;
header.targetId = newTargetId;
data = original.data;
}
public byte[] GetHeaderBytes()
{
var size = Marshal.SizeOf(header);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] GetGameMessageBytes()
{
var size = Marshal.SizeOf(gameMessage);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(gameMessage, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] GetBytes()
{
var outBytes = new byte[header.subpacketSize];
Array.Copy(GetHeaderBytes(), 0, outBytes, 0, SUBPACKET_SIZE);
if (header.type == 0x3)
Array.Copy(GetGameMessageBytes(), 0, outBytes, SUBPACKET_SIZE, GAMEMESSAGE_SIZE);
Array.Copy(data, 0, outBytes, SUBPACKET_SIZE + (header.type == 0x3 ? GAMEMESSAGE_SIZE : 0), data.Length);
return outBytes;
}
public void DebugPrintSubPacket()
{
#if DEBUG
logger.ColorDebug(
string.Format("Size:0x{0:X} Opcode:0x{1:X}{2}{3}", header.subpacketSize, gameMessage.opcode,
Environment.NewLine,
Utils.ByteArrayToHex(GetHeaderBytes())), ConsoleOutputColor.DarkRed);
if (header.type == 0x03)
{
logger.ColorDebug(Utils.ByteArrayToHex(GetGameMessageBytes(), SUBPACKET_SIZE),
ConsoleOutputColor.DarkRed);
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
ConsoleOutputColor.DarkMagenta);
}
#endif
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{
class ErrorPacket
{
public uint errorCode;
public bool invalidPacket = false;
public ErrorPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
errorCode = binReader.ReadUInt32();
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{
class SessionBeginPacket
{
public bool invalidPacket = false;
public SessionBeginPacket(byte[] data)
{
}
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Receive
{
class SessionEndPacket
{
public uint destinationZoneId;
public ushort destinationSpawnType;
public float destinationX;
public float destinationY;
public float destinationZ;
public float destinationRot;
public bool invalidPacket = false;
public SessionEndPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
destinationZoneId = binReader.ReadUInt32();
destinationSpawnType = binReader.ReadUInt16();
destinationX = binReader.ReadSingle();
destinationY = binReader.ReadSingle();
destinationZ = binReader.ReadSingle();
destinationRot = binReader.ReadSingle();
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View file

@ -0,0 +1,27 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send
{
class SessionBeginConfirmPacket
{
public const ushort OPCODE = 0x1000;
public const uint PACKET_SIZE = 0x28;
public static SubPacket BuildPacket(Session session, ushort errorCode = 0)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)session.id);
binWriter.Write((UInt16)errorCode);
}
}
return new SubPacket(true, OPCODE, 0, session.id, data);
}
}
}

View file

@ -0,0 +1,28 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send
{
class SessionEndConfirmPacket
{
public const ushort OPCODE = 0x1001;
public const uint PACKET_SIZE = 0x30;
public static SubPacket BuildPacket(Session session, uint destinationZone, ushort errorCode = 0)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)session.id);
binWriter.Write((UInt16)errorCode);
binWriter.Write((UInt32)destinationZone);
}
}
return new SubPacket(true, OPCODE, 0, session.id, data);
}
}
}

View file

@ -0,0 +1,37 @@
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send
{
class WorldRequestZoneChangePacket
{
public const ushort OPCODE = 0x1002;
public const uint PACKET_SIZE = 0x048;
public static SubPacket BuildPacket(uint sessionId, uint destinationZoneId, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)sessionId);
binWriter.Write((UInt32)destinationZoneId);
binWriter.Write((UInt16)spawnType);
binWriter.Write((Single)spawnX);
binWriter.Write((Single)spawnY);
binWriter.Write((Single)spawnZ);
binWriter.Write((Single)spawnRotation);
}
}
return new SubPacket(OPCODE, sessionId, sessionId, data);
}
}
}

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class ActorDoEmotePacket class ActorDoEmotePacket

View file

@ -4,6 +4,8 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class ActorInstantiatePacket class ActorInstantiatePacket

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorQuestGraphicPacket class SetActorQuestGraphicPacket

View file

@ -1,4 +1,8 @@
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class AddActorPacket class AddActorPacket
{ {

View file

@ -1,4 +1,7 @@
using System.IO; using FFXIVClassic.Common;
using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {

View file

@ -1,4 +1,8 @@
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class DeleteAllActorsPacket class DeleteAllActorsPacket
{ {

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class MoveActorToPositionPacket class MoveActorToPositionPacket

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class RemoveActorPacket class RemoveActorPacket

View file

@ -1,5 +1,7 @@
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorAppearancePacket class SetActorAppearancePacket

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorIconPacket class SetActorIconPacket

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorIdleAnimationPacket class SetActorIdleAnimationPacket

View file

@ -1,4 +1,6 @@
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorIsZoningPacket class SetActorIsZoningPacket
{ {

View file

@ -2,6 +2,8 @@
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorNamePacket class SetActorNamePacket

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorPositionPacket class SetActorPositionPacket
@ -22,7 +24,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
public const float INNPOS_Z = 165.050003f; public const float INNPOS_Z = 165.050003f;
public const float INNPOS_ROT = -1.530000f; public const float INNPOS_ROT = -1.530000f;
public static SubPacket BuildPacket(uint sourceActorID, uint targetActorID, uint actorId, float x, float y, float z, float rotation, uint spawnType, bool isZoningPlayer) public static SubPacket BuildPacket(uint sourceActorID, uint targetActorID, uint actorId, float x, float y, float z, float rotation, ushort spawnType, bool isZoningPlayer)
{ {
byte[] data = new byte[PACKET_SIZE-0x20]; byte[] data = new byte[PACKET_SIZE-0x20];

View file

@ -5,6 +5,8 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorPropetyPacket class SetActorPropetyPacket

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor

View file

@ -1,4 +1,7 @@
using System; using FFXIVClassic.Common;
using System;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {

View file

@ -1,6 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorStatusAllPacket class SetActorStatusAllPacket

View file

@ -1,6 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorStatusPacket class SetActorStatusPacket

View file

@ -1,5 +1,7 @@
using System; using System;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorTargetAnimatedPacket class SetActorTargetAnimatedPacket

View file

@ -1,4 +1,5 @@
using System; using FFXIVClassic.Common;
using System;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {

View file

@ -1,7 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class _0x132Packet class _0x132Packet

View file

@ -1,5 +1,7 @@
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class _0xFPacket class _0xFPacket

View file

@ -1,4 +1,6 @@
namespace FFXIVClassic_Map_Server.packets.send.actor.battle using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{ {
class BattleAction class BattleAction
{ {

View file

@ -1,6 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{ {
class BattleActionX00Packet class BattleActionX00Packet

View file

@ -1,6 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{ {
class BattleActionX01Packet class BattleActionX01Packet

View file

@ -1,6 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{ {
class BattleActionX10Packet class BattleActionX10Packet

View file

@ -1,6 +1,9 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{ {
class BattleActionX18Packet class BattleActionX18Packet

View file

@ -1,8 +1,11 @@
using FFXIVClassic_Map_Server.actors; using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.actors;
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetEmoteEventCondition class SetEmoteEventCondition

View file

@ -2,6 +2,8 @@
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetEventStatus class SetEventStatus

View file

@ -3,6 +3,8 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetNoticeEventCondition class SetNoticeEventCondition

View file

@ -3,6 +3,8 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetPushEventConditionWithCircle class SetPushEventConditionWithCircle

View file

@ -3,6 +3,8 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetPushEventConditionWithFan class SetPushEventConditionWithFan

View file

@ -3,6 +3,8 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetPushEventConditionWithTriggerBox class SetPushEventConditionWithTriggerBox

View file

@ -3,6 +3,8 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetTalkEventCondition class SetTalkEventCondition

View file

@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class EquipmentListX01Packet class EquipmentListX01Packet
{ {

View file

@ -3,7 +3,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class EquipmentListX08Packet class EquipmentListX08Packet
{ {

View file

@ -3,7 +3,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class EquipmentListX16Packet class EquipmentListX16Packet
{ {

View file

@ -3,7 +3,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class EquipmentListX32Packet class EquipmentListX32Packet
{ {

View file

@ -3,7 +3,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class EquipmentListX64Packet class EquipmentListX64Packet
{ {

View file

@ -1,4 +1,6 @@
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryBeginChangePacket class InventoryBeginChangePacket
{ {

View file

@ -1,4 +1,6 @@
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryEndChangePacket class InventoryEndChangePacket
{ {

View file

@ -2,7 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryItemEndPacket class InventoryItemEndPacket
{ {

View file

@ -2,7 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryItemPacket class InventoryItemPacket
{ {

View file

@ -1,6 +1,8 @@
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryListX01Packet class InventoryListX01Packet

View file

@ -3,6 +3,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryListX08Packet class InventoryListX08Packet

View file

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{ {
class InventoryListX16Packet class InventoryListX16Packet

Some files were not shown because too many files have changed in this diff Show more