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.IO;
using System.Runtime.InteropServices;
using FFXIVClassic.Common;
using NLog;
using NLog.Targets;
using Ionic.Zlib;
namespace FFXIVClassic_Map_Server.packets
namespace FFXIVClassic.Common
{
[StructLayout(LayoutKind.Sequential)]
public struct BasePacketHeader
@ -295,6 +295,41 @@ namespace FFXIVClassic_Map_Server.packets
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)
{
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
}

View file

@ -38,6 +38,9 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<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">
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
<Private>True</Private>
@ -56,12 +59,14 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BasePacket.cs" />
<Compile Include="Bitfield.cs" />
<Compile Include="Blowfish.cs" />
<Compile Include="EfficientHashTables.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sql.cs" />
<Compile Include="STA_INIFile.cs" />
<Compile Include="SubPacket.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>

View file

@ -4,7 +4,7 @@ using FFXIVClassic.Common;
using NLog;
using NLog.Targets;
namespace FFXIVClassic_Lobby_Server.packets
namespace FFXIVClassic.Common
{
[StructLayout(LayoutKind.Sequential)]
public struct SubPacketHeader
@ -72,26 +72,38 @@ namespace FFXIVClassic_Lobby_Server.packets
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();
if (isGameMessage)
{
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;
}
header.sourceId = sourceId;
header.targetId = targetId;
if (isGameMessage)
header.type = 0x03;
else
header.type = opcode;
header.unknown1 = 0x00;
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)
@ -141,6 +153,41 @@ namespace FFXIVClassic_Lobby_Server.packets
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()
{
#if DEBUG
@ -157,6 +204,9 @@ namespace FFXIVClassic_Lobby_Server.packets
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
ConsoleOutputColor.DarkMagenta);
}
else
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE),
ConsoleOutputColor.DarkMagenta);
#endif
}
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<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="NLog" version="4.3.5" targetFramework="net45" />
</packages>

View file

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

View file

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

View file

@ -38,13 +38,13 @@
<target xsi:type="ColoredConsole" name="packets"
layout="${message}">
<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" />
<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" />
<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" />
</target>
</targets>

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using FFXIVClassic_Lobby_Server.packets;
using FFXIVClassic.Common;
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.Collections.Generic;
using System.IO;

View file

@ -1,4 +1,5 @@
using System;
using FFXIVClassic.Common;
using System;
using System.IO;
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.Collections.Generic;
using System.IO;

View file

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

View file

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

View file

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

View file

@ -1,4 +1,5 @@
using System;
using FFXIVClassic.Common;
using System;
using System.Collections.Generic;
using System.IO;
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.Collections.Generic;
using System.IO;

View file

@ -1,40 +1,25 @@
using System;
using System.Collections.Generic;
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_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets;
using System.IO;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server;
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.actors.chara.player;
using FFXIVClassic_Map_Server.Properties;
using FFXIVClassic_Map_Server.Actors;
namespace FFXIVClassic_Map_Server
{
class CommandProcessor
{
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList;
private static Dictionary<uint, Item> gamedataItems = Server.GetGamedataItems();
// 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
const UInt32 ITEM_GIL = 1000001;
public CommandProcessor(Dictionary<uint, ConnectedPlayer> playerList)
{
mConnectedPlayerList = playerList;
}
public void ChangeProperty(uint id, uint value, string target)
{
SetActorPropetyPacket ChangeProperty = new SetActorPropetyPacket(target);
@ -43,9 +28,11 @@ namespace FFXIVClassic_Map_Server
ChangeProperty.AddInt(id, value);
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);
packet.DebugPrintPacket();
@ -60,13 +47,13 @@ namespace FFXIVClassic_Map_Server
/// </summary>
/// <param name="client"></param>
/// <param name="message"></param>
private void SendMessage(ConnectedPlayer client, String message)
private void SendMessage(Session session, String message)
{
if (client != null)
client.GetActor().QueuePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message));
if (session != null)
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(""))
return false;
@ -88,7 +75,9 @@ namespace FFXIVClassic_Map_Server
if (cmd.Any())
{
// 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"))
{
@ -125,11 +114,11 @@ namespace FFXIVClassic_Map_Server
if (split[0].Equals("reloaditems"))
{
Program.Log.Info(String.Format("Got request to reload item gamedata"));
SendMessage(client, "Reloading Item Gamedata...");
SendMessage(session, "Reloading Item Gamedata...");
gamedataItems.Clear();
gamedataItems = Database.GetItemGamedata();
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;
}
#endregion

View file

@ -30,7 +30,7 @@ namespace FFXIVClassic_Map_Server
INIFile configIni = new INIFile("./map_config.ini");
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1");
ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "54992");
ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "1989");
ConfigConstants.OPTIONS_TIMESTAMP = configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true");
ConfigConstants.DATABASE_WORLDID = UInt32.Parse(configIni.GetValue("Database", "worldid", "0"));

View file

@ -5,7 +5,7 @@ using System.Collections.Generic;
using System.Linq;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.utils;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.packets.send.player;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.Actors;
@ -258,6 +258,8 @@ namespace FFXIVClassic_Map_Server
positionY = @y,
positionZ = @z,
rotation = @rot,
destinationZoneId = @destZone,
destinationSpawnType = @destSpawn,
currentZoneId = @zoneId
WHERE id = @charaId
";
@ -269,6 +271,8 @@ namespace FFXIVClassic_Map_Server
cmd.Parameters.AddWithValue("@z", player.positionZ);
cmd.Parameters.AddWithValue("@rot", player.rotation);
cmd.Parameters.AddWithValue("@zoneId", player.zoneId);
cmd.Parameters.AddWithValue("@destZone", player.destinationZone);
cmd.Parameters.AddWithValue("@destSpawn", player.destinationSpawnType);
cmd.ExecuteNonQuery();
}
@ -402,7 +406,9 @@ namespace FFXIVClassic_Map_Server
tribe,
restBonus,
achievementPoints,
playTime
playTime,
destinationZoneId,
destinationSpawnType
FROM characters WHERE id = @charId";
cmd = new MySqlCommand(query, conn);
@ -420,7 +426,6 @@ namespace FFXIVClassic_Map_Server
player.currentMainState = reader.GetUInt16(5);
player.zoneId = reader.GetUInt32(6);
player.isZoning = true;
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
player.gcCurrent = reader.GetByte(7);
player.gcRankLimsa = reader.GetByte(8);
player.gcRankGridania = reader.GetByte(9);
@ -434,6 +439,13 @@ namespace FFXIVClassic_Map_Server
player.playerWork.restBonusExpRate = reader.GetInt32(17);
player.achievementPoints = reader.GetUInt32(18);
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\StaticActors.cs" />
<Compile Include="actors\world\WorldMaster.cs" />
<Compile Include="ClientConnection.cs" />
<Compile Include="dataobjects\ZoneConnection.cs" />
<Compile Include="CommandProcessor.cs" />
<Compile Include="ConfigConstants.cs" />
<Compile Include="Database.cs" />
@ -112,7 +112,7 @@
<Compile Include="actors\chara\player\PlayerWork.cs" />
<Compile Include="dataobjects\DBWorld.cs" />
<Compile Include="dataobjects\InventoryItem.cs" />
<Compile Include="dataobjects\ConnectedPlayer.cs" />
<Compile Include="dataobjects\Session.cs" />
<Compile Include="dataobjects\Item.cs" />
<Compile Include="dataobjects\RecruitmentDetails.cs" />
<Compile Include="dataobjects\SeamlessBoundry.cs" />
@ -124,7 +124,6 @@
<Compile Include="lua\LuaPlayer.cs" />
<Compile Include="lua\LuaScript.cs" />
<Compile Include="PacketProcessor.cs" />
<Compile Include="packets\BasePacket.cs" />
<Compile Include="packets\receive\ChatMessagePacket.cs" />
<Compile Include="packets\receive\events\EventUpdatePacket.cs" />
<Compile Include="packets\receive\events\EventStartPacket.cs" />
@ -258,9 +257,13 @@
<Compile Include="packets\send\_0x02Packet.cs" />
<Compile Include="packets\send\_0x10Packet.cs" />
<Compile Include="packets\send\_0xE2Packet.cs" />
<Compile Include="packets\SubPacket.cs" />
<Compile Include="packets\receive\PingPacket.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="Properties\AssemblyInfo.cs" />
<Compile Include="lua\LuaUtils.cs" />
@ -286,6 +289,7 @@
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
<Compile Include="packets\WorldPackets\Send\WorldRequestZoneChangePacket.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">

View file

@ -38,13 +38,13 @@
<target xsi:type="ColoredConsole" name="packets"
layout="${message}">
<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" />
<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" />
<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" />
</target>
</targets>
@ -55,6 +55,7 @@
<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.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"
<logger name="*" minlevel="Debug" writeTo="f" />

View file

@ -1,5 +1,5 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
@ -18,165 +18,86 @@ using FFXIVClassic_Map_Server.packets.send.recruitment;
using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
using FFXIVClassic_Map_Server.packets.WorldPackets.Receive;
namespace FFXIVClassic_Map_Server
{
class PacketProcessor
{
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;
cp = new CommandProcessor(playerList);
}
public void ProcessPacket(ClientConnection client, BasePacket packet)
public void ProcessPacket(ZoneConnection client, SubPacket subpacket)
{
if (packet.header.isCompressed == 0x01)
BasePacket.DecryptPacket(client.blowfish, ref packet);
Session session = mServer.GetSession(subpacket.header.targetId);
List<SubPacket> subPackets = packet.GetSubpackets();
foreach (SubPacket subpacket in subPackets)
{
if (subpacket.header.type == 0x01)
{
packet.DebugPrintPacket();
byte[] reply1Data = {
0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFD, 0xFF, 0xFF,
0xE5, 0x6E, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x0
};
byte[] reply2Data = {
0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x38, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2B, 0x5F, 0x26,
0x66, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xAF, 0x2B, 0x38, 0x2B, 0x5F, 0x26, 0xB8, 0x8D, 0xF0, 0x2B,
0xC8, 0xFD, 0x85, 0xFE, 0xA8, 0x7C, 0x5B, 0x09, 0x38, 0x2B, 0x5F, 0x26, 0xC8, 0xD6, 0xAF, 0x2B,
0xB8, 0x8D, 0xF0, 0x2B, 0x88, 0xAF, 0x5E, 0x26
};
BasePacket reply1 = new BasePacket(reply1Data);
BasePacket reply2 = new BasePacket(reply2Data);
//Write Timestamp into Reply1
using (MemoryStream mem = new MemoryStream(reply1.data))
{
using (BinaryWriter binReader = new BinaryWriter(mem))
{
binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
binReader.Write((UInt32)Utils.UnixTimeStampUTC());
}
}
//Read in Actor Id that owns this connection
uint actorID = 0;
using (MemoryStream mem = new MemoryStream(packet.data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
byte[] readIn = new byte[12];
binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
binReader.Read(readIn, 0, 12);
actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn));
}
catch (Exception)
{ }
}
}
//Should never happen.... unless actor id IS 0!
if (actorID == 0)
break;
client.owner = actorID;
//Write Actor ID into reply2
using (MemoryStream mem = new MemoryStream(reply2.data))
{
using (BinaryWriter binReader = new BinaryWriter(mem))
{
binReader.BaseStream.Seek(0x10, SeekOrigin.Begin);
binReader.Write(actorID);
}
}
ConnectedPlayer player = null;
if (packet.header.connectionType == BasePacket.TYPE_ZONE)
{
while (mPlayers != null && !mPlayers.ContainsKey(client.owner))
{ }
player = mPlayers[client.owner];
}
//Create connected player if not Created
if (player == null)
{
player = new ConnectedPlayer(actorID);
mPlayers[actorID] = player;
}
player.SetConnection(packet.header.connectionType, client);
if (packet.header.connectionType == BasePacket.TYPE_ZONE)
Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "zone", actorID, client.GetAddress());
else if (packet.header.connectionType == BasePacket.TYPE_CHAT)
Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "chat", actorID, client.GetAddress());
//Create player actor
reply1.DebugPrintPacket();
client.QueuePacket(reply1);
client.QueuePacket(reply2);
break;
}
else if (subpacket.header.type == 0x07)
{
BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x08);
//client.QueuePacket(init);
}
else if (subpacket.header.type == 0x08)
{
//Response, client's current [actorID][time]
//BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x07);
//client.QueuePacket(init);
packet.DebugPrintPacket();
}
else if (subpacket.header.type == 0x03)
{
ConnectedPlayer player = null;
if(mPlayers.ContainsKey(client.owner))
player = mPlayers[client.owner];
if (player == null || !player.IsClientConnectionsReady())
if (session == null && subpacket.gameMessage.opcode != 0x1000)
return;
//Normal Game Opcode
switch (subpacket.gameMessage.opcode)
{
//World Server - Error
case 0x100A:
ErrorPacket worldError = new ErrorPacket(subpacket.data);
switch (worldError.errorCode)
{
case 0x01:
session.GetActor().SendGameMessage(Server.GetWorldManager().GetActor(), 60005, 0x20);
break;
}
break;
//World Server - Session Begin
case 0x1000:
subpacket.DebugPrintSubPacket();
session = mServer.AddSession(subpacket.header.targetId);
if (session.GetActor().destinationZone != 0)
Server.GetWorldManager().DoZoneIn(session.GetActor(), false, session.GetActor().destinationSpawnType);
Program.Log.Info("{0} has been added to the session list.", session.GetActor().customDisplayName);
client.FlushQueuedSendPackets();
break;
//World Server - Session End
case 0x1001:
SessionEndPacket endSessionPacket = new SessionEndPacket(subpacket.data);
if (endSessionPacket.destinationZoneId == 0)
session.GetActor().CleanupAndSave();
else
session.GetActor().CleanupAndSave(endSessionPacket.destinationZoneId, endSessionPacket.destinationSpawnType, endSessionPacket.destinationX, endSessionPacket.destinationY, endSessionPacket.destinationZ, endSessionPacket.destinationRot);
Server.GetServer().RemoveSession(session.id);
Program.Log.Info("{0} has been removed from the session list.", session.GetActor().customDisplayName);
client.QueuePacket(SessionEndConfirmPacket.BuildPacket(session, endSessionPacket.destinationZoneId), true, false);
client.FlushQueuedSendPackets();
break;
//Ping
case 0x0001:
//subpacket.DebugPrintSubPacket();
PingPacket pingPacket = new PingPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(player.actorID, pingPacket.time), true, false));
player.Ping();
client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(session.id, pingPacket.time), true, false));
session.Ping();
break;
//Unknown
case 0x0002:
subpacket.DebugPrintSubPacket();
client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false);
session = mServer.AddSession(subpacket.header.targetId);
client.QueuePacket(_0x2Packet.BuildPacket(session.id), true, false);
Server.GetWorldManager().DoLogin(player.GetActor());
LuaEngine.OnBeginLogin(session.GetActor());
Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1);
LuaEngine.OnLogin(session.GetActor());
client.FlushQueuedSendPackets();
break;
//Chat Received
@ -187,17 +108,17 @@ namespace FFXIVClassic_Map_Server
if (chatMessage.message.StartsWith("!"))
{
if (cp.DoCommand(chatMessage.message, player))
continue;
if (Server.GetCommandProcessor().DoCommand(chatMessage.message, session))
return; ;
}
player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false);
session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false);
break;
//Langauge Code
case 0x0006:
LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
player.languageCode = langCode.languageCode;
session.languageCode = langCode.languageCode;
break;
//Unknown - Happens a lot at login, then once every time player zones
case 0x0007:
@ -207,13 +128,12 @@ namespace FFXIVClassic_Map_Server
//Update Position
case 0x00CA:
//Update Position
//subpacket.DebugPrintSubPacket();
UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
player.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
player.GetActor().SendInstanceUpdate();
session.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
session.GetActor().SendInstanceUpdate();
if (player.GetActor().IsInZoneChange())
player.GetActor().SetZoneChanging(false);
if (session.GetActor().IsInZoneChange())
session.GetActor().SetZoneChanging(false);
break;
//Set Target
@ -221,13 +141,13 @@ namespace FFXIVClassic_Map_Server
//subpacket.DebugPrintSubPacket();
SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
player.GetActor().currentTarget = setTarget.actorID;
player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true);
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);
player.GetActor().currentLockedTarget = lockTarget.actorID;
session.GetActor().currentLockedTarget = lockTarget.actorID;
break;
//Start Event
case 0x012D:
@ -250,19 +170,19 @@ namespace FFXIVClassic_Map_Server
Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
player.GetActor().currentEventName = eventStart.triggerName;
session.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
session.GetActor().currentEventName = eventStart.triggerName;
if (ownerActor == null)
{
//Is it a instance actor?
ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
ownerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
if (ownerActor == null)
{
//Is it a Director?
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
ownerActor = player.GetActor().currentDirector;
if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
ownerActor = session.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));
@ -271,7 +191,7 @@ namespace FFXIVClassic_Map_Server
}
}
player.GetActor().StartEvent(ownerActor, eventStart);
session.GetActor().StartEvent(ownerActor, eventStart);
Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
break;
@ -285,42 +205,42 @@ namespace FFXIVClassic_Map_Server
Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
/*
//Is it a static actor? If not look in the player's instance
Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner);
Actor updateOwnerActor = Server.GetStaticActors(session.GetActor().currentEventOwner);
if (updateOwnerActor == null)
{
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
updateOwnerActor = player.GetActor().currentDirector;
if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
updateOwnerActor = session.GetActor().currentDirector;
if (updateOwnerActor == null)
break;
}
*/
player.GetActor().UpdateEvent(eventUpdate);
session.GetActor().UpdateEvent(eventUpdate);
//LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate);
//LuaEngine.DoActorOnEventUpdated(session.GetActor(), updateOwnerActor, eventUpdate);
break;
case 0x012F:
//subpacket.DebugPrintSubPacket();
ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
if (paramRequest.paramName.Equals("charaWork/exp"))
player.GetActor().SendCharaExpInfo();
session.GetActor().SendCharaExpInfo();
break;
/* RECRUITMENT */
//Start Recruiting
case 0x01C3:
StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false));
client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(session.id, true), true, false));
break;
//End Recruiting
case 0x01C4:
client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false));
client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(session.id), true, false));
break;
//Party Window Opened, Request State
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;
//Search Recruiting
case 0x01C7:
@ -336,7 +256,7 @@ namespace FFXIVClassic_Map_Server
details.subTaskId = 1;
details.comment = "This is a test details packet sent by the server. No implementation has been Created yet...";
details.num[0] = 1;
client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(player.actorID, details), true, false));
client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(session.id, details), true, false));
break;
//Accepted Recruiting
case 0x01C6:
@ -345,74 +265,71 @@ namespace FFXIVClassic_Map_Server
/* SOCIAL STUFF */
case 0x01C9:
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;
case 0x01CA:
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;
case 0x01CB:
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;
case 0x01CC:
AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(player.actorID, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false));
client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(session.id, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false));
break;
case 0x01CD:
AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false));
client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(session.id, true, RemoveFriendList.name), true, false));
break;
case 0x01CE:
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;
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;
/* SUPPORT DESK STUFF */
//Request for FAQ/Info List
case 0x01D0:
FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, new string[] { "Testing FAQ1", "Coded style!" }), true, false));
client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(session.id, new string[] { "Testing FAQ1", "Coded style!" }), true, false));
break;
//Request for body of a faq/info selection
case 0x01D1:
FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, "HERE IS A GIANT BODY. Nothing else to say!"), true, false));
client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(session.id, "HERE IS A GIANT BODY. Nothing else to say!"), true, false));
break;
//Request issue list
case 0x01D2:
GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false));
client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(session.id, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }), true, false));
break;
//Request if GM ticket exists
case 0x01D3:
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, false), true, false));
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(session.id, false), true, false));
break;
//Request for GM response message
case 0x01D4:
client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false));
client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(session.id, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false));
break;
//GM Ticket Sent
case 0x01D5:
GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, true), true, false));
client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(session.id, true), true, false));
break;
//Request to end ticket
case 0x01D6:
client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false));
client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(session.id), true, false));
break;
default:
Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
subpacket.DebugPrintSubPacket();
break;
}
}
else
packet.DebugPrintPacket();
}
}
}

View file

@ -63,14 +63,14 @@ namespace FFXIVClassic_Map_Server
if (startServer)
{
Server server = new Server();
CommandProcessor cp = new CommandProcessor(server.GetConnectedPlayerList());
server.StartServer();
while (startServer)
{
String input = Console.ReadLine();
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.Net;
using System.Net.Sockets;
using System.Threading;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic.Common;
using NLog;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
@ -17,7 +15,6 @@ namespace FFXIVClassic_Map_Server
public const int FFXIV_MAP_PORT = 54992;
public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF
public const int BACKLOG = 100;
public const int HEALTH_THREAD_SLEEP_TIME = 5;
public const string STATIC_ACTORS_PATH = "./staticactors.bin";
@ -25,60 +22,28 @@ namespace FFXIVClassic_Map_Server
private Socket mServerSocket;
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint, ConnectedPlayer>();
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();
private LuaEngine mLuaEngine = new LuaEngine();
private static CommandProcessor mCommandProcessor = new CommandProcessor();
private static ZoneConnection mWorldConnection = new ZoneConnection();
private static WorldManager mWorldManager;
private static Dictionary<uint, Item> gamedataItems;
private static Dictionary<uint, Item> mGamedataItems;
private static StaticActors mStaticActors;
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()
{
mSelf = this;
}
public static Server GetServer()
{
return mSelf;
}
public bool StartServer()
{
mConnectionHealthThread = new Thread(new ThreadStart(ConnectionHealth));
mConnectionHealthThread.Name = "MapThread:Health";
//mConnectionHealthThread.Start();
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
gamedataItems = Database.GetItemGamedata();
Program.Log.Info("Loaded {0} items.", gamedataItems.Count);
mGamedataItems = Database.GetItemGamedata();
Program.Log.Info("Loaded {0} items.", mGamedataItems.Count);
mWorldManager = new WorldManager(this);
mWorldManager.LoadZoneList();
@ -88,11 +53,11 @@ namespace FFXIVClassic_Map_Server
mWorldManager.LoadSpawnLocations();
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
{
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)
{
@ -120,39 +85,72 @@ namespace FFXIVClassic_Map_Server
Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
Console.ForegroundColor = ConsoleColor.Gray;
mProcessor = new PacketProcessor(this, mConnectedPlayerList, mConnectionList);
mProcessor = new PacketProcessor(this);
//mGameThread = new Thread(new ThreadStart(mProcessor.update));
//mGameThread.Start();
return true;
}
public void RemovePlayer(Player player)
#region Session Handling
public Session AddSession(uint id)
{
lock (mConnectedPlayerList)
if (mSessionList.ContainsKey(id))
return mSessionList[id];
Session session = new Session(id);
mSessionList.Add(id, session);
return session;
}
public void RemoveSession(uint id)
{
if (mConnectedPlayerList.ContainsKey(player.actorId))
mConnectedPlayerList.Remove(player.actorId);
if (mSessionList.ContainsKey(id))
{
mSessionList.Remove(id);
}
}
public Session GetSession(uint id)
{
if (mSessionList.ContainsKey(id))
return mSessionList[id];
else
return null;
}
public Session GetSession(string name)
{
foreach (Session s in mSessionList.Values)
{
if (s.GetActor().customDisplayName.ToLower().Equals(name.ToLower()))
return s;
}
return null;
}
public Dictionary<uint, Session> GetSessionList()
{
return mSessionList;
}
#endregion
#region Socket Handling
private void AcceptCallback(IAsyncResult result)
{
ClientConnection conn = null;
ZoneConnection conn = null;
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
try
{
conn = new ClientConnection();
conn = new ZoneConnection();
conn.socket = socket.EndAccept(result);
conn.buffer = new byte[BUFFER_SIZE];
lock (mConnectionList)
{
mConnectionList.Add(conn);
}
mWorldConnection = conn;
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port);
//Queue recieving of data from the connection
@ -164,11 +162,7 @@ namespace FFXIVClassic_Map_Server
{
if (conn != null)
{
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
mWorldConnection = null;
}
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
}
@ -176,53 +170,25 @@ namespace FFXIVClassic_Map_Server
{
if (conn != null)
{
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
mWorldConnection = null;
}
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>
/// 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>
/// <param name="result"></param>
private void ReceiveCallback(IAsyncResult result)
{
ClientConnection conn = (ClientConnection)result.AsyncState;
ZoneConnection conn = (ZoneConnection)result.AsyncState;
//Check if disconnected
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
{
if (mConnectedPlayerList.ContainsKey(conn.owner))
mConnectedPlayerList.Remove(conn.owner);
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
if (conn.connType == BasePacket.TYPE_ZONE)
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
return;
mWorldConnection = null;
Program.Log.Info("Disconnected from world server!");
}
try
@ -238,13 +204,13 @@ namespace FFXIVClassic_Map_Server
//Build packets until can no longer or out of data
while (true)
{
BasePacket basePacket = BuildPacket(ref offset, conn.buffer, bytesRead);
SubPacket subPacket = SubPacket.CreatePacket(ref offset, conn.buffer, bytesRead);
//If can't build packet, break, else process another
if (basePacket == null)
if (subPacket == null)
break;
else
mProcessor.ProcessPacket(conn, basePacket);
mProcessor.ProcessPacket(conn, subPacket);
}
//Not all bytes consumed, transfer leftover to beginning
@ -265,79 +231,63 @@ namespace FFXIVClassic_Map_Server
}
else
{
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
mWorldConnection = null;
Program.Log.Info("Disconnected from world server!");
}
}
catch (SocketException)
{
if (conn.socket != null)
{
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
lock (mConnectionList)
{
mConnectionList.Remove(conn);
mWorldConnection = null;
Program.Log.Info("Disconnected from world server!");
}
}
}
}
/// <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
public static ZoneConnection GetWorldConnection()
{
return mWorldConnection;
}
public static Server GetServer()
{
return mSelf;
}
public static CommandProcessor GetCommandProcessor()
{
return mCommandProcessor;
}
public static WorldManager GetWorldManager()
{
return mWorldManager;
}
public Dictionary<uint, ConnectedPlayer> GetConnectedPlayerList()
{
return mConnectedPlayerList;
}
public static Dictionary<uint, Item> GetGamedataItems()
{
return gamedataItems;
return mGamedataItems;
}
public static Actor GetStaticActors(uint id)
{
return mStaticActors.GetActor(id);
}
public static Actor GetStaticActors(string name)
{
return mStaticActors.FindStaticActor(name);
}
public static Item GetItemGamedata(uint id)
{
if (mGamedataItems.ContainsKey(id))
return mGamedataItems[id];
else
return null;
}
}

View file

@ -62,10 +62,13 @@ namespace FFXIVClassic_Map_Server
canStealth,
isInstanceRaid
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);
cmd.Parameters.AddWithValue("@ip", ConfigConstants.OPTIONS_BINDIP);
cmd.Parameters.AddWithValue("@port", ConfigConstants.OPTIONS_PORT);
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
@ -334,13 +337,20 @@ namespace FFXIVClassic_Map_Server
{
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;
if (!reader.IsDBNull(11))
customName = reader.GetString("customDisplayName");
uint classId = reader.GetUInt32("actorClassId");
string uniqueId = reader.GetString("uniqueId");
uint zoneId = reader.GetUInt32("zoneId");
string privAreaName = reader.GetString("privateAreaName");
uint privAreaLevel = reader.GetUInt32("privateAreaLevel");
float x = reader.GetFloat("positionX");
@ -350,15 +360,6 @@ namespace FFXIVClassic_Map_Server
ushort state = reader.GetUInt16("actorState");
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);
zone.AddSpawnLocation(spawn);
@ -524,13 +525,6 @@ namespace FFXIVClassic_Map_Server
//Moves actor to new zone, and sends packets to spawn at the given coords.
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
Area newArea;
@ -542,15 +536,16 @@ namespace FFXIVClassic_Map_Server
//This server does not contain that zoneId
if (newArea == null)
{
if (oldZone != null)
{
oldZone.AddActorToZone(player);
Program.Log.Debug("Request to change to zone not on this server by: {0}.", player.customDisplayName);
RequestWorldServerZoneChange(player, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation);
return;
}
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;
Area oldZone = player.zone;
//Remove player from currentZone if transfer else it's login
if (player.zone != null)
{
oldZone.RemoveActorFromZone(player);
}
newArea.AddActorToZone(player);
@ -613,8 +608,8 @@ namespace FFXIVClassic_Map_Server
}
}
//Login Zone In
public void DoLogin(Player player)
//Session started, zone into world
public void DoZoneIn(Player player, bool isLogin, ushort spawnType)
{
//Add player to new zone and update
Zone zone = GetZone(player.zoneId);
@ -626,14 +621,24 @@ namespace FFXIVClassic_Map_Server
//Set the current zone and add player
player.zone = zone;
LuaEngine.OnBeginLogin(player);
zone.AddActorToZone(player);
//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);
}
@ -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)
{
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.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
@ -71,7 +71,7 @@ namespace FFXIVClassic_Map_Server.Actors
return SetActorSpeedPacket.BuildPacket(actorId, playerActorId);
}
public SubPacket CreateSpawnPositonPacket(uint playerActorId, uint spawnType)
public SubPacket CreateSpawnPositonPacket(uint playerActorId, ushort spawnType)
{
SubPacket spawnPacket;
if (!spawnedFirstTime && playerActorId == actorId)
@ -92,7 +92,7 @@ namespace FFXIVClassic_Map_Server.Actors
return spawnPacket;
}
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, uint spawnType)
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, ushort spawnType)
{
SubPacket spawnPacket;
@ -224,7 +224,7 @@ namespace FFXIVClassic_Map_Server.Actors
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>();
subpackets.Add(CreateAddActorPacket(playerActorId, 8));

View file

@ -1,6 +1,6 @@
using FFXIVClassic_Map_Server;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.area;
using FFXIVClassic_Map_Server.actors.chara.npc;
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.lua;
using FFXIVClassic_Map_Server.packets.send.actor;

View file

@ -1,6 +1,6 @@
using FFXIVClassic_Map_Server;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.chara.npc;
using FFXIVClassic_Map_Server.Actors;
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.packets.send.actor;
@ -35,6 +36,8 @@ namespace FFXIVClassic_Map_Server.Actors
public const int L_INDEXFINGER = 26;
public const int UNKNOWN = 27;
public bool isStatic = false;
public uint modelId;
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.dataobjects;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send.actor;
using FFXIVClassic_Map_Server.utils;
@ -88,11 +88,15 @@ namespace FFXIVClassic_Map_Server.Actors
Player player = Server.GetWorldManager().GetPCInWorld(playerActorId);
lParams = DoActorInit(player);
if (lParams != null && lParams.Count >= 3 && lParams[2].typeID == 0 && (int)lParams[2].value == 0)
isStatic = true;
if (lParams == null)
{
string classPathFake = "/Chara/Npc/Populace/PopulaceStandard";
string classNameFake = "PopulaceStandard";
lParams = LuaUtils.CreateLuaParamList(classPathFake, false, false, false, false, false, 0xF47F6, false, false, 0, 0);
isStatic = true;
//ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams).DebugPrintSubPacket();
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);
}
public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
public override BasePacket GetSpawnPackets(uint playerActorId, ushort spawnType)
{
List<SubPacket> subpackets = new List<SubPacket>();
subpackets.Add(CreateAddActorPacket(playerActorId));

View file

@ -1,7 +1,6 @@
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
using System.Collections.Generic;
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.dataobjects;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
using System;
using System.Collections.Generic;
using System.Linq;

View file

@ -1,5 +1,5 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.actors.chara.player;
using FFXIVClassic_Map_Server.actors.director;
using FFXIVClassic_Map_Server.dataobjects;
@ -7,8 +7,6 @@ using FFXIVClassic_Map_Server.dataobjects.chara;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send;
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.list;
using FFXIVClassic_Map_Server.packets.send.player;
@ -17,6 +15,7 @@ using System;
using System.Collections.Generic;
using MoonSharp.Interpreter;
using FFXIVClassic_Map_Server.packets.receive.events;
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
namespace FFXIVClassic_Map_Server.Actors
{
@ -85,6 +84,8 @@ namespace FFXIVClassic_Map_Server.Actors
public Coroutine currentEventRunning;
//Player Info
public uint destinationZone;
public ushort destinationSpawnType;
public uint[] timers = new uint[20];
public ushort currentJob;
public uint currentTitle;
@ -124,9 +125,9 @@ namespace FFXIVClassic_Map_Server.Actors
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;
actorName = String.Format("_pc{0:00000000}", actorID);
@ -260,7 +261,7 @@ namespace FFXIVClassic_Map_Server.Actors
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>();
subpackets.Add(CreateAddActorPacket(playerActorId, 8));
@ -481,7 +482,7 @@ namespace FFXIVClassic_Map_Server.Actors
QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId));
QueuePacket(GetSpawnPackets(actorId, spawnType));
GetSpawnPackets(actorId, spawnType).DebugPrintPacket();
//GetSpawnPackets(actorId, spawnType).DebugPrintPacket();
#region grouptest
//Retainers
@ -654,15 +655,38 @@ namespace FFXIVClassic_Map_Server.Actors
public void CleanupAndSave()
{
playerSession.LockUpdates(true);
//Remove actor from zone and main server list
zone.RemoveActorFromZone(this);
Server.GetServer().RemovePlayer(this);
//Set Destination to 0
this.destinationZone = 0;
this.destinationSpawnType = 0;
//Save Player
Database.SavePlayerPlayTime(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()
@ -731,7 +755,7 @@ namespace FFXIVClassic_Map_Server.Actors
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));
}
@ -741,7 +765,7 @@ namespace FFXIVClassic_Map_Server.Actors
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));
else
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams)));
@ -749,7 +773,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams)
{
if (msgParams.Length == 0)
if (msgParams == null || msgParams.Length == 0)
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log));
else
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams)));
@ -757,7 +781,7 @@ namespace FFXIVClassic_Map_Server.Actors
public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams)
{
if (msgParams.Length == 0)
if (msgParams == null || msgParams.Length == 0)
QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, actorId, textIdOwner.actorId, textId, displayId, log));
else
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.packets.send.actor;
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.lua;
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.lua;
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.lua;
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.lua;
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.lua;
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.lua;
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.packets.send.actor;
using System.Collections.Generic;

View file

@ -1,6 +1,6 @@
using FFXIVClassic_Map_Server;
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.lua;
using FFXIVClassic_Map_Server.packets.send.actor;
@ -12,66 +12,33 @@ using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.dataobjects
{
class ConnectedPlayer
class Session
{
public uint actorID = 0;
public uint id = 0;
Player playerActor;
public List<Actor> actorInstanceList = new List<Actor>();
public uint languageCode = 1;
private ClientConnection zoneConnection;
private ClientConnection chatConnection;
private uint lastPingPacket = Utils.UnixTimeStampUTC();
public bool isUpdatesLocked = true;
public string errorMessage = "";
public ConnectedPlayer(uint actorId)
public Session(uint sessionId)
{
this.actorID = actorId;
playerActor = new Player(this, actorId);
this.id = sessionId;
playerActor = new Player(this, sessionId);
actorInstanceList.Add(playerActor);
}
public void SetConnection(int type, ClientConnection conn)
{
conn.connType = type;
switch (type)
{
case BasePacket.TYPE_ZONE:
zoneConnection = conn;
break;
case BasePacket.TYPE_CHAT:
chatConnection = conn;
break;
}
}
public bool IsClientConnectionsReady()
{
return (zoneConnection != null && chatConnection != null);
}
public void Disconnect()
{
zoneConnection.Disconnect();
chatConnection.Disconnect();
}
public bool IsDisconnected()
{
return (!zoneConnection.IsConnected() && !chatConnection.IsConnected());
}
public void QueuePacket(BasePacket basePacket)
{
zoneConnection.QueuePacket(basePacket);
Server.GetWorldConnection().QueuePacket(basePacket);
}
public void QueuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted)
{
zoneConnection.QueuePacket(subPacket, isAuthed, isEncrypted);
Server.GetWorldConnection().QueuePacket(subPacket, isAuthed, isEncrypted);
}
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)
{
if (isUpdatesLocked)
return;
playerActor.oldPositionX = playerActor.positionX;
playerActor.oldPositionY = playerActor.positionY;
playerActor.oldPositionZ = playerActor.positionZ;
@ -115,6 +85,9 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void UpdateInstance(List<Actor> list)
{
if (isUpdatesLocked)
return;
List<BasePacket> basePackets = new List<BasePacket>();
List<SubPacket> RemoveActorSubpackets = new List<SubPacket>();
List<SubPacket> posUpdateSubpackets = new List<SubPacket>();
@ -139,6 +112,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
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));
}
else
@ -163,5 +140,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
actorInstanceList.Clear();
}
public void LockUpdates(bool f)
{
isUpdatesLocked = f;
}
}
}

View file

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

View file

@ -1,4 +1,4 @@
using FFXIVClassic_Map_Server.packets;

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,8 @@
using System;
using System.IO;
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class SetActorPositionPacket
@ -22,7 +24,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
public const float INNPOS_Z = 165.050003f;
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];

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,9 @@ using System;
using System.Collections.Generic;
using System.IO;
namespace FFXIVClassic_Map_Server.packets.send.Actor.inventory
using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.packets.send.actor.inventory
{
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
{

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
{

View file

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

View file

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

View file

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

View file

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

View file

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

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