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();
gameMessage = new GameMessageHeader();
gameMessage.opcode = opcode; if (isGameMessage)
{
gameMessage = new GameMessageHeader();
gameMessage.opcode = opcode;
gameMessage.timestamp = Utils.UnixTimeStampUTC();
gameMessage.unknown4 = 0x14;
gameMessage.unknown5 = 0x00;
gameMessage.unknown6 = 0x00;
}
header.sourceId = sourceId; header.sourceId = sourceId;
header.targetId = targetId; header.targetId = targetId;
gameMessage.timestamp = Utils.UnixTimeStampUTC(); if (isGameMessage)
header.type = 0x03;
else
header.type = opcode;
header.type = 0x03;
header.unknown1 = 0x00; header.unknown1 = 0x00;
gameMessage.unknown4 = 0x14;
gameMessage.unknown5 = 0x00;
gameMessage.unknown6 = 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,7 +204,10 @@ 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);
@ -419,8 +425,7 @@ namespace FFXIVClassic_Map_Server
player.oldRotation = player.rotation = reader.GetFloat(4); player.oldRotation = player.rotation = reader.GetFloat(4);
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;
@ -17,402 +17,319 @@ using FFXIVClassic_Map_Server.packets.receive.recruitment;
using FFXIVClassic_Map_Server.packets.send.recruitment; 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);
if (session == null && subpacket.gameMessage.opcode != 0x1000)
return;
List<SubPacket> subPackets = packet.GetSubpackets(); //Normal Game Opcode
foreach (SubPacket subpacket in subPackets) switch (subpacket.gameMessage.opcode)
{ {
if (subpacket.header.type == 0x01) //World Server - Error
{ case 0x100A:
packet.DebugPrintPacket(); ErrorPacket worldError = new ErrorPacket(subpacket.data);
byte[] reply1Data = { switch (worldError.errorCode)
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, case 0x01:
0xE5, 0x6E, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x0 session.GetActor().SendGameMessage(Server.GetWorldManager().GetActor(), 60005, 0x20);
}; break;
}
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; 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
case 0x0001:
//subpacket.DebugPrintSubPacket();
PingPacket pingPacket = new PingPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(session.id, pingPacket.time), true, false));
session.Ping();
break;
//Unknown
case 0x0002:
client.owner = actorID; subpacket.DebugPrintSubPacket();
session = mServer.AddSession(subpacket.header.targetId);
//Write Actor ID into reply2 client.QueuePacket(_0x2Packet.BuildPacket(session.id), true, false);
using (MemoryStream mem = new MemoryStream(reply2.data))
{ LuaEngine.OnBeginLogin(session.GetActor());
using (BinaryWriter binReader = new BinaryWriter(mem)) Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1);
LuaEngine.OnLogin(session.GetActor());
client.FlushQueuedSendPackets();
break;
//Chat Received
case 0x0003:
ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data);
Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
subpacket.DebugPrintSubPacket();
if (chatMessage.message.StartsWith("!"))
{ {
binReader.BaseStream.Seek(0x10, SeekOrigin.Begin); if (Server.GetCommandProcessor().DoCommand(chatMessage.message, session))
binReader.Write(actorID); return; ;
} }
}
session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false);
ConnectedPlayer player = null; break;
//Langauge Code
if (packet.header.connectionType == BasePacket.TYPE_ZONE) case 0x0006:
{ LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
while (mPlayers != null && !mPlayers.ContainsKey(client.owner)) session.languageCode = langCode.languageCode;
{ } break;
player = mPlayers[client.owner]; //Unknown - Happens a lot at login, then once every time player zones
} case 0x0007:
//subpacket.DebugPrintSubPacket();
//Create connected player if not Created _0x07Packet unknown07 = new _0x07Packet(subpacket.data);
if (player == null) break;
{ //Update Position
player = new ConnectedPlayer(actorID); case 0x00CA:
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;
//Normal Game Opcode
switch (subpacket.gameMessage.opcode)
{
//Ping
case 0x0001:
//subpacket.DebugPrintSubPacket();
PingPacket pingPacket = new PingPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(player.actorID, pingPacket.time), true, false));
player.Ping();
break;
//Unknown
case 0x0002:
subpacket.DebugPrintSubPacket();
client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false);
Server.GetWorldManager().DoLogin(player.GetActor());
break;
//Chat Received
case 0x0003:
ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data);
Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
subpacket.DebugPrintSubPacket();
if (chatMessage.message.StartsWith("!"))
{
if (cp.DoCommand(chatMessage.message, player))
continue;
}
player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false);
break;
//Langauge Code
case 0x0006:
LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
player.languageCode = langCode.languageCode;
break;
//Unknown - Happens a lot at login, then once every time player zones
case 0x0007:
//subpacket.DebugPrintSubPacket();
_0x07Packet unknown07 = new _0x07Packet(subpacket.data);
break;
//Update Position //Update Position
case 0x00CA: UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
//Update Position session.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
//subpacket.DebugPrintSubPacket(); session.GetActor().SendInstanceUpdate();
UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
player.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); if (session.GetActor().IsInZoneChange())
player.GetActor().SendInstanceUpdate(); session.GetActor().SetZoneChanging(false);
break;
//Set Target
case 0x00CD:
//subpacket.DebugPrintSubPacket();
SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
session.GetActor().currentTarget = setTarget.actorID;
session.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(session.id, session.id, setTarget.actorID), true);
break;
//Lock Target
case 0x00CC:
LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
session.GetActor().currentLockedTarget = lockTarget.actorID;
break;
//Start Event
case 0x012D:
subpacket.DebugPrintSubPacket();
EventStartPacket eventStart = new EventStartPacket(subpacket.data);
/*
if (eventStart.error != null)
{
player.errorMessage += eventStart.error;
if (eventStart.errorIndex == eventStart.errorNum - 1)
Program.Log.Error("\n"+player.errorMessage);
if (player.GetActor().IsInZoneChange())
player.GetActor().SetZoneChanging(false);
break; break;
//Set Target }
case 0x00CD: */
//subpacket.DebugPrintSubPacket();
SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
player.GetActor().currentTarget = setTarget.actorID;
player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true);
break;
//Lock Target
case 0x00CC:
LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
player.GetActor().currentLockedTarget = lockTarget.actorID;
break;
//Start Event
case 0x012D:
subpacket.DebugPrintSubPacket();
EventStartPacket eventStart = new EventStartPacket(subpacket.data);
/*
if (eventStart.error != null)
{
player.errorMessage += eventStart.error;
if (eventStart.errorIndex == eventStart.errorNum - 1)
Program.Log.Error("\n"+player.errorMessage);
break;
}
*/
Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID; session.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
player.GetActor().currentEventName = eventStart.triggerName; session.GetActor().currentEventName = eventStart.triggerName;
if (ownerActor == null)
{
//Is it a instance actor?
ownerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
if (ownerActor == null) if (ownerActor == null)
{ {
//Is it a instance actor? //Is it a Director?
ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner); if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
if (ownerActor == null) ownerActor = session.GetActor().currentDirector;
else
{ {
//Is it a Director? 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));
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
ownerActor = player.GetActor().currentDirector;
else
{
Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
break;
}
}
}
player.GetActor().StartEvent(ownerActor, eventStart);
Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
break;
//Unknown, happens at npc spawn and cutscene play????
case 0x00CE:
break;
//Event Result
case 0x012E:
subpacket.DebugPrintSubPacket();
EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data);
Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
/*
//Is it a static actor? If not look in the player's instance
Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner);
if (updateOwnerActor == null)
{
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
updateOwnerActor = player.GetActor().currentDirector;
if (updateOwnerActor == null)
break; break;
} }
*/ }
player.GetActor().UpdateEvent(eventUpdate); }
//LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate); 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));
break;
//Unknown, happens at npc spawn and cutscene play????
case 0x00CE:
break;
//Event Result
case 0x012E:
subpacket.DebugPrintSubPacket();
EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data);
Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
/*
//Is it a static actor? If not look in the player's instance
Actor updateOwnerActor = Server.GetStaticActors(session.GetActor().currentEventOwner);
if (updateOwnerActor == null)
{
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
updateOwnerActor = session.GetActor().currentDirector;
if (updateOwnerActor == null)
break;
}
*/
session.GetActor().UpdateEvent(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:
RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data); RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data);
break; break;
//Get Recruitment Details //Get Recruitment Details
case 0x01C8: case 0x01C8:
RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data); RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data);
RecruitmentDetails details = new RecruitmentDetails(); RecruitmentDetails details = new RecruitmentDetails();
details.recruiterName = "Localhost Character"; details.recruiterName = "Localhost Character";
details.purposeId = 2; details.purposeId = 2;
details.locationId = 1; details.locationId = 1;
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:
subpacket.DebugPrintSubPacket(); subpacket.DebugPrintSubPacket();
break; break;
/* 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,40 +85,73 @@ 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 (mSessionList.ContainsKey(id))
{ {
if (mConnectedPlayerList.ContainsKey(player.actorId)) mSessionList.Remove(id);
mConnectedPlayerList.Remove(player.actorId);
} }
} }
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
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn); conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
@ -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

@ -61,11 +61,14 @@ namespace FFXIVClassic_Map_Server
canRideChocobo, canRideChocobo,
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())
@ -333,14 +336,21 @@ namespace FFXIVClassic_Map_Server
using (MySqlDataReader reader = cmd.ExecuteReader()) using (MySqlDataReader reader = cmd.ExecuteReader())
{ {
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");
string uniqueId = reader.GetString("uniqueId");
uint classId = reader.GetUInt32("actorClassId");
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");
@ -349,16 +359,7 @@ namespace FFXIVClassic_Map_Server
float rot = reader.GetFloat("rotation"); float rot = reader.GetFloat("rotation");
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);
@ -523,14 +524,7 @@ 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,17 +536,18 @@ 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);
}
var message = "WorldManager.DoZoneChange: unable to change areas, new area is not valid.";
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM, "[Debug]", message);
Program.Log.Debug(message);
return; return;
} }
Area oldZone = player.zone;
//Remove player from currentZone if transfer else it's login
if (player.zone != null)
{
oldZone.RemoveActorFromZone(player);
}
newArea.AddActorToZone(player); newArea.AddActorToZone(player);
//Update player actor's properties //Update player actor's properties
@ -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);
@ -625,15 +620,25 @@ 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;
@ -86,13 +86,17 @@ namespace FFXIVClassic_Map_Server.Actors
List<LuaParam> lParams; List<LuaParam> lParams;
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,7 +15,8 @@ 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
{ {
class Player : Character class Player : Character
@ -84,7 +83,9 @@ 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);
@ -258,9 +259,9 @@ namespace FFXIVClassic_Map_Server.Actors
else else
lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true); lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true);
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
@ -653,16 +654,39 @@ 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()
@ -730,8 +754,8 @@ 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));
} }
@ -740,24 +764,24 @@ 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)));
} }
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)));
} }
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,207 +1,208 @@
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;
using FFXIVClassic_Map_Server.packets.receive.events; using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send; using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.packets.send.events; using FFXIVClassic_Map_Server.packets.send.events;
using MoonSharp.Interpreter; using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop; using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Loaders; using MoonSharp.Interpreter.Loaders;
using System; using System;
using System.Collections.Generic; 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
class LuaEngine {
{ class LuaEngine
const string FILEPATH_PLAYER = "./scripts/player.lua"; {
const string FILEPATH_ZONE = "./scripts/zones/{0}/zone.lua"; const string FILEPATH_PLAYER = "./scripts/player.lua";
const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua"; const string FILEPATH_ZONE = "./scripts/zones/{0}/zone.lua";
const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua"; const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua";
const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.lua"; const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua";
const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.lua";
public LuaEngine()
{ public LuaEngine()
UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic; {
} UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic;
public static List<LuaParam> DoActorInstantiate(Player player, Actor target)
{
string luaPath;
if (target is Npc)
{
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
{
LuaScript script = LoadScript(luaPath);
if (script == null)
return null;
DynValue result = script.Call(script.Globals["init"], target);
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
return lparams;
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
return null;
}
}
return null;
} }
public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart) public static List<LuaParam> DoActorInstantiate(Player player, Actor target)
{ {
string luaPath; string luaPath;
if (target is Command) if (target is Npc)
{ {
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
} if (File.Exists(luaPath))
else if (target is Director) {
{ LuaScript script = LoadScript(luaPath);
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
} if (script == null)
else return null;
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
DynValue result = script.Call(script.Globals["init"], target);
if (File.Exists(luaPath)) List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
{ return lparams;
LuaScript script = LoadScript(luaPath); }
else
if (script == null) {
return null; SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
return null;
if (!script.Globals.Get("onEventStarted").IsNil()) }
return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine;
else
return null;
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
return null;
} }
} return null;
}
public static void DoActorOnSpawn(Player player, Npc target)
{ public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart)
string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName()); {
if (File.Exists(luaPath))
{
LuaScript script = LoadScript(luaPath);
if (script == null)
return;
//Run Script
if (!script.Globals.Get("onSpawn").IsNil())
script.Call(script.Globals["onSpawn"], player, target);
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
}
}
public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate)
{
if (target is Npc)
{
((Npc)target).DoEventUpdate(player, eventUpdate);
return;
}
string luaPath; string luaPath;
if (target is Command) if (target is Command)
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName()); {
else if (target is Director) luaPath = String.Format(FILEPATH_COMMANDS, target.GetName());
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
else
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
{
LuaScript script = LoadScript(luaPath);
if (script == null)
return;
//Have to Do this to combine LuaParams
List<Object> objects = new List<Object>();
objects.Add(player);
objects.Add(target);
objects.Add(eventUpdate.val2);
objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams));
//Run Script
if (!script.Globals.Get("onEventUpdate").IsNil())
script.Call(script.Globals["onEventUpdate"], objects.ToArray());
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
} }
} else if (target is Director)
{
public static void OnZoneIn(Player player) luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
{ }
else
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
{
LuaScript script = LoadScript(luaPath);
if (script == null)
return null;
if (!script.Globals.Get("onEventStarted").IsNil())
return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine;
else
return null;
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
return null;
}
}
public static void DoActorOnSpawn(Player player, Npc target)
{
string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
{
LuaScript script = LoadScript(luaPath);
if (script == null)
return;
//Run Script
if (!script.Globals.Get("onSpawn").IsNil())
script.Call(script.Globals["onSpawn"], player, target);
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
}
}
public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate)
{
if (target is Npc)
{
((Npc)target).DoEventUpdate(player, eventUpdate);
return;
}
string luaPath;
if (target is Command)
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName());
else if (target is Director)
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
else
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
if (File.Exists(luaPath))
{
LuaScript script = LoadScript(luaPath);
if (script == null)
return;
//Have to Do this to combine LuaParams
List<Object> objects = new List<Object>();
objects.Add(player);
objects.Add(target);
objects.Add(eventUpdate.val2);
objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams));
//Run Script
if (!script.Globals.Get("onEventUpdate").IsNil())
script.Call(script.Globals["onEventUpdate"], objects.ToArray());
}
else
{
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
}
}
public static void OnZoneIn(Player player)
{
string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId); string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId);
if (File.Exists(luaPath)) if (File.Exists(luaPath))
{ {
LuaScript script = LoadScript(luaPath); LuaScript script = LoadScript(luaPath);
if (script == null) if (script == null)
return; return;
//Run Script //Run Script
if (!script.Globals.Get("onZoneIn").IsNil()) if (!script.Globals.Get("onZoneIn").IsNil())
script.Call(script.Globals["onZoneIn"], player); script.Call(script.Globals["onZoneIn"], player);
} }
} }
public static void OnBeginLogin(Player player) public static void OnBeginLogin(Player player)
{ {
if (File.Exists(FILEPATH_PLAYER)) if (File.Exists(FILEPATH_PLAYER))
{ {
LuaScript script = LoadScript(FILEPATH_PLAYER); LuaScript script = LoadScript(FILEPATH_PLAYER);
if (script == null) if (script == null)
return; return;
//Run Script //Run Script
if (!script.Globals.Get("onBeginLogin").IsNil()) if (!script.Globals.Get("onBeginLogin").IsNil())
script.Call(script.Globals["onBeginLogin"], player); script.Call(script.Globals["onBeginLogin"], player);
} }
} }
public static void OnLogin(Player player) public static void OnLogin(Player player)
{ {
if (File.Exists(FILEPATH_PLAYER)) if (File.Exists(FILEPATH_PLAYER))
{ {
LuaScript script = LoadScript(FILEPATH_PLAYER); LuaScript script = LoadScript(FILEPATH_PLAYER);
if (script == null) if (script == null)
return; return;
//Run Script //Run Script
if (!script.Globals.Get("onLogin").IsNil()) if (!script.Globals.Get("onLogin").IsNil())
script.Call(script.Globals["onLogin"], player); script.Call(script.Globals["onLogin"], player);
} }
} }
#region RunGMCommand #region RunGMCommand
public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false) public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false)
{ {
@ -336,22 +337,22 @@ namespace FFXIVClassic_Map_Server.lua
LuaScript.Log.Error("LuaEngine.RunGMCommand: Unable to find script {0}", path); LuaScript.Log.Error("LuaEngine.RunGMCommand: Unable to find script {0}", path);
return; return;
} }
#endregion #endregion
public static LuaScript LoadScript(string filename) public static LuaScript LoadScript(string filename)
{ {
LuaScript script = LoadGlobals(); LuaScript script = LoadGlobals();
try try
{ {
script.DoFile(filename); script.DoFile(filename);
} }
catch (SyntaxErrorException e) catch (SyntaxErrorException e)
{ {
Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage); Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage);
return null; return null;
} }
return script; return script;
} }
public static LuaScript LoadGlobals(LuaScript script = null) public static LuaScript LoadGlobals(LuaScript script = null)
@ -367,57 +368,57 @@ namespace FFXIVClassic_Map_Server.lua
script.Options.DebugPrint = s => { Program.Log.Debug(s); }; script.Options.DebugPrint = s => { Program.Log.Debug(s); };
return script; return script;
} }
public static void SendError(Player player, string message) public static void SendError(Player player, string message)
{ {
List<SubPacket> SendError = new List<SubPacket>(); List<SubPacket> SendError = new List<SubPacket>();
SendError.Add(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName)); SendError.Add(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName));
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", message); player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", message);
player.playerSession.QueuePacket(BasePacket.CreatePacket(SendError, true, false)); player.playerSession.QueuePacket(BasePacket.CreatePacket(SendError, true, false));
} }
internal static void DoDirectorOnTalked(Director director, Player player, Npc npc) internal static void DoDirectorOnTalked(Director director, Player player, Npc npc)
{ {
string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName()); string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName());
if (File.Exists(luaPath)) if (File.Exists(luaPath))
{ {
LuaScript script = LoadScript(luaPath); LuaScript script = LoadScript(luaPath);
if (script == null) if (script == null)
return; return;
//Run Script //Run Script
if (!script.Globals.Get("onTalked").IsNil()) if (!script.Globals.Get("onTalked").IsNil())
script.Call(script.Globals["onTalked"], player, npc); script.Call(script.Globals["onTalked"], player, npc);
} }
else else
{ {
SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName()));
} }
} }
internal static void DoDirectorOnCommand(Director director, Player player, Command command) internal static void DoDirectorOnCommand(Director director, Player player, Command command)
{ {
string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName()); string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName());
if (File.Exists(luaPath)) if (File.Exists(luaPath))
{ {
LuaScript script = LoadScript(luaPath); LuaScript script = LoadScript(luaPath);
if (script == null) if (script == null)
return; return;
//Run Script //Run Script
if (!script.Globals.Get("onCommand").IsNil()) if (!script.Globals.Get("onCommand").IsNil())
script.Call(script.Globals["onCommand"], player, command); script.Call(script.Globals["onCommand"], player, command);
} }
else else
{ {
SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName())); SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName()));
} }
} }
} }
} }

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,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class ActorDoEmotePacket class ActorDoEmotePacket
{ {

View file

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

View file

@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
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,6 +1,9 @@
using System.IO; using FFXIVClassic.Common;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class BattleAction1Packet class BattleAction1Packet
{ {

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,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class MoveActorToPositionPacket class MoveActorToPositionPacket
{ {

View file

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

View file

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

View file

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

View file

@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
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,7 +2,9 @@
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorNamePacket class SetActorNamePacket
{ {

View file

@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
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,7 +5,9 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class SetActorPropetyPacket class SetActorPropetyPacket
{ {

View file

@ -1,7 +1,8 @@
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
{ {
class SetActorSpeedPacket class SetActorSpeedPacket
{ {

View file

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

View file

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

View file

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

View file

@ -1,6 +1,8 @@
using System; using System;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
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,8 +1,10 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{ {
class _0x132Packet class _0x132Packet
{ {

View file

@ -1,6 +1,8 @@
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor using FFXIVClassic.Common;
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,7 +1,10 @@
using System; using FFXIVClassic.Common;
using System;
using System.IO; using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.battle
{ {
class BattleActionX00Packet class BattleActionX00Packet
{ {

View file

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

View file

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

View file

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

View file

@ -1,9 +1,12 @@
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;
namespace FFXIVClassic_Map_Server.packets.send.actor.events using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.events
{ {
class SetEmoteEventCondition class SetEmoteEventCondition
{ {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,9 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace FFXIVClassic_Map_Server.packets.send.actor.events using FFXIVClassic.Common;
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,7 +1,9 @@
using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.dataobjects;
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 InventoryListX01Packet class InventoryListX01Packet
{ {

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 InventoryListX08Packet class InventoryListX08Packet
{ {

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 InventoryListX16Packet class InventoryListX16Packet
{ {

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