mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-20 03:37:48 +00:00
Merged Ioncannon/ffxiv-classic-server into master
This commit is contained in:
commit
5ccc2435b0
656 changed files with 24304 additions and 4976 deletions
|
@ -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
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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, byte[] data) : this(true, opcode, sourceId, data) { }
|
||||
|
||||
public SubPacket(bool isGameMessage, ushort opcode, uint sourceId, 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 = 0;
|
||||
|
||||
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)
|
||||
|
@ -105,6 +117,11 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
data = original.data;
|
||||
}
|
||||
|
||||
public void SetTargetId(uint target)
|
||||
{
|
||||
this.header.targetId = target;
|
||||
}
|
||||
|
||||
public byte[] GetHeaderBytes()
|
||||
{
|
||||
var size = Marshal.SizeOf(header);
|
||||
|
@ -141,6 +158,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 +209,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
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -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;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace FFXIVClassic_Lobby_Server
|
||||
{
|
||||
|
@ -23,7 +25,7 @@ namespace FFXIVClassic_Lobby_Server
|
|||
if (!File.Exists("./lobby_config.ini"))
|
||||
{
|
||||
Program.Log.Error("FILE NOT FOUND!");
|
||||
return false;
|
||||
Program.Log.Error("Loading defaults...");
|
||||
}
|
||||
|
||||
INIFile configIni = new INIFile("./lobby_config.ini");
|
||||
|
@ -40,5 +42,49 @@ namespace FFXIVClassic_Lobby_Server
|
|||
|
||||
return true;
|
||||
}
|
||||
public static void ApplyLaunchArgs(string[] launchArgs)
|
||||
{
|
||||
var args = (from arg in launchArgs select arg.ToLower().Trim().TrimStart('-')).ToList();
|
||||
|
||||
for (var i = 0; i + 1 < args.Count; i += 2)
|
||||
{
|
||||
var arg = args[i];
|
||||
var val = args[i + 1];
|
||||
var legit = false;
|
||||
|
||||
if (arg == "ip")
|
||||
{
|
||||
IPAddress ip;
|
||||
if (IPAddress.TryParse(val, out ip) && (legit = true))
|
||||
OPTIONS_BINDIP = val;
|
||||
}
|
||||
else if (arg == "port")
|
||||
{
|
||||
UInt16 port;
|
||||
if (UInt16.TryParse(val, out port) && (legit = true))
|
||||
OPTIONS_PORT = val;
|
||||
}
|
||||
else if (arg == "user" && (legit = true))
|
||||
{
|
||||
DATABASE_USERNAME = val;
|
||||
}
|
||||
else if (arg == "p" && (legit = true))
|
||||
{
|
||||
DATABASE_PASSWORD = val;
|
||||
}
|
||||
else if (arg == "db" && (legit = true))
|
||||
{
|
||||
DATABASE_NAME = val;
|
||||
}
|
||||
else if (arg == "host" && (legit = true))
|
||||
{
|
||||
DATABASE_HOST = val;
|
||||
}
|
||||
if (!legit)
|
||||
{
|
||||
Program.Log.Error("Invalid parameter <{0}> for argument: <--{1}> or argument doesnt exist!", val, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props') AND '$(OS)' == 'Windows_NT'" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props') AND '$(OS)' == 'Windows_NT'" />
|
||||
<Import Project="..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.0.0-beta3\build\Microsoft.Net.Compilers.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
|
@ -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" />
|
||||
|
@ -135,7 +133,7 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy "$(SolutionDir)data\lobby_config.ini" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d</PostBuildEvent>
|
||||
<PostBuildEvent>xcopy "$(SolutionDir)data\lobby_config.ini" "$(SolutionDir)$(ProjectName)\$(OutDir)" /y</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace FFXIVClassic_Lobby_Server
|
|||
{
|
||||
ErrorPacket errorPacket = new ErrorPacket(sessionPacket.sequence, 0, 0, 13001, "Your session has expired, please login again.");
|
||||
SubPacket subpacket = errorPacket.BuildPacket();
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
BasePacket errorBasePacket = BasePacket.CreatePacket(subpacket, true, false);
|
||||
BasePacket.EncryptPacket(client.blowfish, errorBasePacket);
|
||||
client.QueuePacket(errorBasePacket);
|
||||
|
|
|
@ -20,13 +20,16 @@ namespace FFXIVClassic_Lobby_Server
|
|||
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
|
||||
Debug.Listeners.Add(myWriter);
|
||||
#endif
|
||||
Program.Log.Info("--------FFXIV 1.0 Lobby Server--------");
|
||||
Log.Info("==================================");
|
||||
Log.Info("FFXIV Classic Lobby Server");
|
||||
Log.Info("Version: 0.1");
|
||||
Log.Info("==================================");
|
||||
|
||||
bool startServer = true;
|
||||
|
||||
//Load Config
|
||||
if (!ConfigConstants.Load())
|
||||
startServer = false;
|
||||
ConfigConstants.Load();
|
||||
ConfigConstants.ApplyLaunchArgs(args);
|
||||
|
||||
//Test DB Connection
|
||||
Program.Log.Info("Testing DB connection to \"{0}\"... ", ConfigConstants.DATABASE_HOST);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
@ -60,7 +61,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
accountCount = 0;
|
||||
}
|
||||
|
@ -87,7 +89,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
@ -58,7 +59,7 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
|
||||
return new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
return new SubPacket(OPCODE, 0xe0006868, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -86,7 +87,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
characterCount = 0;
|
||||
}
|
||||
|
@ -132,7 +134,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
characterCount = 0;
|
||||
}
|
||||
|
@ -144,7 +147,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
@ -37,7 +38,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
return subpacket;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
@ -63,7 +64,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
namesCount = 0;
|
||||
}
|
||||
|
@ -90,7 +92,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
@ -64,7 +65,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
retainerCount = 0;
|
||||
}
|
||||
|
@ -91,7 +93,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
@ -48,7 +49,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
data = memStream.GetBuffer();
|
||||
}
|
||||
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
|
||||
return subPackets;
|
||||
|
|
|
@ -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;
|
||||
|
@ -62,7 +63,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
serverCount = 0;
|
||||
}
|
||||
|
@ -89,7 +91,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||
byte[] data = memStream.GetBuffer();
|
||||
binWriter.Dispose();
|
||||
memStream.Dispose();
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||
subpacket.SetTargetId(0xe0006868);
|
||||
subPackets.Add(subpacket);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,72 +1,36 @@
|
|||
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();
|
||||
private static Dictionary<uint, ItemData> 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);
|
||||
|
||||
ChangeProperty.SetTarget(target);
|
||||
ChangeProperty.AddInt(id, value);
|
||||
ChangeProperty.AddTarget();
|
||||
|
||||
foreach (KeyValuePair<uint, ConnectedPlayer> entry in mConnectedPlayerList)
|
||||
{
|
||||
SubPacket ChangePropertyPacket = ChangeProperty.BuildPacket((entry.Value.actorID), (entry.Value.actorID));
|
||||
|
||||
BasePacket packet = BasePacket.CreatePacket(ChangePropertyPacket, true, false);
|
||||
packet.DebugPrintPacket();
|
||||
|
||||
entry.Value.QueuePacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We only use the default options for SendMessagePacket.
|
||||
/// May as well make it less unwieldly to view
|
||||
/// </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, 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;
|
||||
|
@ -81,14 +45,16 @@ namespace FFXIVClassic_Map_Server
|
|||
)
|
||||
.SelectMany(str => str).ToArray();
|
||||
|
||||
split = split.Select(temp => temp.ToLower()).ToArray(); // Ignore case on commands
|
||||
split = split.ToArray(); // Ignore case on commands
|
||||
|
||||
var cmd = split[0];
|
||||
|
||||
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 +91,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
|
||||
|
@ -139,7 +105,7 @@ namespace FFXIVClassic_Map_Server
|
|||
{
|
||||
if (split.Length == 4)
|
||||
{
|
||||
ChangeProperty(Utils.MurmurHash2(split[1], 0), Convert.ToUInt32(split[2], 16), split[3]);
|
||||
// ChangeProperty(Utils.MurmurHash2(split[1], 0), Convert.ToUInt32(split[2], 16), split[3]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -150,7 +116,7 @@ namespace FFXIVClassic_Map_Server
|
|||
{
|
||||
if (split.Length == 4)
|
||||
{
|
||||
ChangeProperty(Convert.ToUInt32(split[1], 16), Convert.ToUInt32(split[2], 16), split[3]);
|
||||
//ChangeProperty(Convert.ToUInt32(split[1], 16), Convert.ToUInt32(split[2], 16), split[3]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
using FFXIVClassic.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using MoonSharp.Interpreter.Interop;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace FFXIVClassic_Map_Server
|
||||
{
|
||||
|
@ -24,13 +29,13 @@ namespace FFXIVClassic_Map_Server
|
|||
if (!File.Exists("./map_config.ini"))
|
||||
{
|
||||
Program.Log.Error("FILE NOT FOUND");
|
||||
return false;
|
||||
Program.Log.Error("Loading defaults... ");
|
||||
}
|
||||
|
||||
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"));
|
||||
|
@ -42,5 +47,50 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ApplyLaunchArgs(string[] launchArgs)
|
||||
{
|
||||
var args = (from arg in launchArgs select arg.ToLower().Trim().TrimStart('-')).ToList();
|
||||
|
||||
for (var i = 0; i + 1 < args.Count; i += 2)
|
||||
{
|
||||
var arg = args[i];
|
||||
var val = args[i + 1];
|
||||
var legit = false;
|
||||
|
||||
if (arg == "ip")
|
||||
{
|
||||
IPAddress ip;
|
||||
if (IPAddress.TryParse(val, out ip) && (legit = true))
|
||||
OPTIONS_BINDIP = val;
|
||||
}
|
||||
else if (arg == "port")
|
||||
{
|
||||
UInt16 port;
|
||||
if (UInt16.TryParse(val, out port) && (legit = true))
|
||||
OPTIONS_PORT = val;
|
||||
}
|
||||
else if (arg == "user" && (legit = true))
|
||||
{
|
||||
DATABASE_USERNAME = val;
|
||||
}
|
||||
else if (arg == "p" && (legit = true))
|
||||
{
|
||||
DATABASE_PASSWORD = val;
|
||||
}
|
||||
else if (arg == "db" && (legit = true))
|
||||
{
|
||||
DATABASE_NAME = val;
|
||||
}
|
||||
else if (arg == "host" && (legit = true))
|
||||
{
|
||||
DATABASE_HOST = val;
|
||||
}
|
||||
if (!legit)
|
||||
{
|
||||
Program.Log.Error("Invalid parameter <{0}> for argument: <--{1}> or argument doesnt exist!", val, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -48,29 +48,6 @@ namespace FFXIVClassic_Map_Server
|
|||
return id;
|
||||
}
|
||||
|
||||
public static DBWorld GetServer(uint serverId)
|
||||
{
|
||||
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
DBWorld world = null;
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
world = conn.Query<DBWorld>("SELECT * FROM servers WHERE id=@ServerId", new { ServerId = serverId }).SingleOrDefault();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Npc> GetNpcList()
|
||||
{
|
||||
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
|
@ -94,11 +71,11 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
}
|
||||
|
||||
public static Dictionary<uint, Item> GetItemGamedata()
|
||||
public static Dictionary<uint, ItemData> GetItemGamedata()
|
||||
{
|
||||
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
Dictionary<uint, Item> gamedataItems = new Dictionary<uint, Item>();
|
||||
Dictionary<uint, ItemData> gamedataItems = new Dictionary<uint, ItemData>();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -113,6 +90,7 @@ namespace FFXIVClassic_Map_Server
|
|||
LEFT JOIN gamedata_items_armor ON gamedata_items.catalogID = gamedata_items_armor.catalogID
|
||||
LEFT JOIN gamedata_items_weapon ON gamedata_items.catalogID = gamedata_items_weapon.catalogID
|
||||
LEFT JOIN gamedata_items_graphics ON gamedata_items.catalogID = gamedata_items_graphics.catalogID
|
||||
LEFT JOIN gamedata_items_graphics_extra ON gamedata_items.catalogID = gamedata_items_graphics_extra.catalogID
|
||||
";
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||
|
@ -122,16 +100,16 @@ namespace FFXIVClassic_Map_Server
|
|||
while (reader.Read())
|
||||
{
|
||||
uint id = reader.GetUInt32("catalogID");
|
||||
Item item = null;
|
||||
ItemData item = null;
|
||||
|
||||
if (Item.IsWeapon(id))
|
||||
if (ItemData.IsWeapon(id))
|
||||
item = new WeaponItem(reader);
|
||||
else if (Item.IsArmor(id))
|
||||
else if (ItemData.IsArmor(id))
|
||||
item = new ArmorItem(reader);
|
||||
else if (Item.IsAccessory(id))
|
||||
else if (ItemData.IsAccessory(id))
|
||||
item = new AccessoryItem(reader);
|
||||
else
|
||||
item = new Item(reader);
|
||||
item = new ItemData(reader);
|
||||
|
||||
gamedataItems.Add(item.catalogID, item);
|
||||
}
|
||||
|
@ -150,6 +128,47 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
}
|
||||
|
||||
public static Dictionary<uint, GuildleveData> GetGuildleveGamedata()
|
||||
{
|
||||
using (var conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
Dictionary<uint, GuildleveData> gamedataGuildleves = new Dictionary<uint, GuildleveData>();
|
||||
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
string query = @"
|
||||
SELECT
|
||||
*
|
||||
FROM gamedata_guildleves
|
||||
";
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||
|
||||
using (MySqlDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
uint id = reader.GetUInt32("id");
|
||||
GuildleveData guildleve = new GuildleveData(reader);
|
||||
gamedataGuildleves.Add(guildleve.id, guildleve);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
|
||||
return gamedataGuildleves;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SavePlayerAppearance(Player player)
|
||||
{
|
||||
string query;
|
||||
|
@ -259,7 +278,11 @@ namespace FFXIVClassic_Map_Server
|
|||
positionY = @y,
|
||||
positionZ = @z,
|
||||
rotation = @rot,
|
||||
currentZoneId = @zoneId
|
||||
destinationZoneId = @destZone,
|
||||
destinationSpawnType = @destSpawn,
|
||||
currentZoneId = @zoneId,
|
||||
currentPrivateArea = @privateArea,
|
||||
currentPrivateAreaType = @privateAreaType
|
||||
WHERE id = @charaId
|
||||
";
|
||||
|
||||
|
@ -270,6 +293,10 @@ 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("@privateArea", player.privateArea);
|
||||
cmd.Parameters.AddWithValue("@privateAreaType", player.privateAreaType);
|
||||
cmd.Parameters.AddWithValue("@destZone", player.destinationZone);
|
||||
cmd.Parameters.AddWithValue("@destSpawn", player.destinationSpawnType);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
@ -318,6 +345,42 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
}
|
||||
|
||||
public static void SavePlayerHomePoints(Player player)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
UPDATE characters SET
|
||||
homepoint = @homepoint,
|
||||
homepointInn = @homepointInn
|
||||
WHERE id = @charaId
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@homepoint", player.homepoint);
|
||||
cmd.Parameters.AddWithValue("@homepointInn", player.homepointInn);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveQuest(Player player, Quest quest)
|
||||
{
|
||||
int slot = player.GetQuestSlot(quest.actorId);
|
||||
|
@ -343,17 +406,18 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
query = @"
|
||||
INSERT INTO characters_quest_scenario
|
||||
(characterId, slot, questId, questData, questFlags)
|
||||
(characterId, slot, questId, currentPhase, questData, questFlags)
|
||||
VALUES
|
||||
(@charaId, @slot, @questId, @questData, @questFlags)
|
||||
(@charaId, @slot, @questId, @phase, @questData, @questFlags)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
questData = @questData, questFlags = @questFlags
|
||||
questId = @questId, currentPhase = @phase, questData = @questData, questFlags = @questFlags
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@slot", slot);
|
||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.actorId);
|
||||
cmd.Parameters.AddWithValue("@phase", quest.GetPhase());
|
||||
cmd.Parameters.AddWithValue("@questData", quest.GetSerializedQuestData());
|
||||
cmd.Parameters.AddWithValue("@questFlags", quest.GetQuestFlags());
|
||||
|
||||
|
@ -370,6 +434,209 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
}
|
||||
|
||||
public static void MarkGuildleve(Player player, uint glId, bool isAbandoned, bool isCompleted)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
UPDATE characters_quest_guildleve_regional
|
||||
SET abandoned = @abandoned, completed = @completed
|
||||
WHERE characterId = @charaId and guildleveId = @guildleveId
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@guildleveId", glId);
|
||||
cmd.Parameters.AddWithValue("@abandoned", isAbandoned);
|
||||
cmd.Parameters.AddWithValue("@completed", isCompleted);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveGuildleve(Player player, uint glId, int slot)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
INSERT INTO characters_quest_guildleve_regional
|
||||
(characterId, slot, guildleveId, abandoned, completed)
|
||||
VALUES
|
||||
(@charaId, @slot, @guildleveId, @abandoned, @completed)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
guildleveId = @guildleveId, abandoned = @abandoned, completed = @completed
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@slot", slot);
|
||||
cmd.Parameters.AddWithValue("@guildleveId", glId);
|
||||
cmd.Parameters.AddWithValue("@abandoned", 0);
|
||||
cmd.Parameters.AddWithValue("@completed", 0);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveGuildleve(Player player, uint glId)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
DELETE FROM characters_quest_guildleve_regional
|
||||
WHERE characterId = @charaId and guildleveId = @guildleveId
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@guildleveId", glId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveQuest(Player player, uint questId)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
DELETE FROM characters_quest_scenario
|
||||
WHERE characterId = @charaId and questId = @questId
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & questId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CompleteQuest(Player player, uint questId)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
INSERT INTO characters_quest_completed
|
||||
(characterId, questId)
|
||||
VALUES
|
||||
(@charaId, @questId)
|
||||
ON DUPLICATE KEY UPDATE characterId=characterId
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & questId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsQuestCompleted(Player player, uint questId)
|
||||
{
|
||||
bool isCompleted = false;
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
MySqlCommand cmd = new MySqlCommand("SELECT * FROM characters_quest_completed WHERE characterId = @charaId and questId = @questId", conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@questId", questId);
|
||||
isCompleted = cmd.ExecuteScalar() != null;
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
return isCompleted;
|
||||
}
|
||||
|
||||
public static void LoadPlayerCharacter(Player player)
|
||||
{
|
||||
string query;
|
||||
|
@ -403,7 +670,13 @@ namespace FFXIVClassic_Map_Server
|
|||
tribe,
|
||||
restBonus,
|
||||
achievementPoints,
|
||||
playTime
|
||||
playTime,
|
||||
destinationZoneId,
|
||||
destinationSpawnType,
|
||||
currentPrivateArea,
|
||||
currentPrivateAreaType,
|
||||
homepoint,
|
||||
homepointInn
|
||||
FROM characters WHERE id = @charId";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
|
@ -421,7 +694,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);
|
||||
|
@ -435,6 +707,22 @@ namespace FFXIVClassic_Map_Server
|
|||
player.playerWork.restBonusExpRate = reader.GetInt32(17);
|
||||
player.achievementPoints = reader.GetUInt32(18);
|
||||
player.playTime = reader.GetUInt32(19);
|
||||
player.homepoint = reader.GetUInt32("homepoint");
|
||||
player.homepointInn = reader.GetByte("homepointInn");
|
||||
player.destinationZone = reader.GetUInt32("destinationZoneId");
|
||||
player.destinationSpawnType = reader.GetByte("destinationSpawnType");
|
||||
|
||||
if (!reader.IsDBNull(reader.GetOrdinal("currentPrivateArea")))
|
||||
player.privateArea = reader.GetString("currentPrivateArea");
|
||||
player.privateAreaType = reader.GetUInt32("currentPrivateAreaType");
|
||||
|
||||
if (player.destinationZone != 0)
|
||||
player.zoneId = player.destinationZone;
|
||||
|
||||
if (player.privateArea != null && !player.privateArea.Equals(""))
|
||||
player.zone = Server.GetWorldManager().GetPrivateArea(player.zoneId, player.privateArea, player.privateAreaType);
|
||||
else
|
||||
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -690,7 +978,8 @@ namespace FFXIVClassic_Map_Server
|
|||
slot,
|
||||
questId,
|
||||
questData,
|
||||
questFlags
|
||||
questFlags,
|
||||
currentPhase
|
||||
FROM characters_quest_scenario WHERE characterId = @charId";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
|
@ -703,6 +992,7 @@ namespace FFXIVClassic_Map_Server
|
|||
player.playerWork.questScenario[index] = 0xA0F00000 | reader.GetUInt32(1);
|
||||
string questData = null;
|
||||
uint questFlags = 0;
|
||||
uint currentPhase = 0;
|
||||
|
||||
if (!reader.IsDBNull(2))
|
||||
questData = reader.GetString(2);
|
||||
|
@ -714,8 +1004,11 @@ namespace FFXIVClassic_Map_Server
|
|||
else
|
||||
questFlags = 0;
|
||||
|
||||
if (!reader.IsDBNull(4))
|
||||
currentPhase = reader.GetUInt32(4);
|
||||
|
||||
string questName = Server.GetStaticActors(player.playerWork.questScenario[index]).actorName;
|
||||
player.questScenario[index] = new Quest(player, player.playerWork.questScenario[index], questName, questData, questFlags);
|
||||
player.questScenario[index] = new Quest(player, player.playerWork.questScenario[index], questName, questData, questFlags, currentPhase);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1246,6 +1539,82 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
return cheevosPacket.BuildPacket(player.actorId);
|
||||
}
|
||||
public static bool CreateLinkshell(Player player, string lsName, ushort lsCrest)
|
||||
{
|
||||
bool success = false;
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
string query = @"
|
||||
INSERT INTO server_linkshells
|
||||
(name, master, crest)
|
||||
VALUES
|
||||
(@lsName, @master, @crest)
|
||||
;
|
||||
";
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@lsName", lsName);
|
||||
cmd.Parameters.AddWithValue("@master", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@crest", lsCrest);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
success = true;
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
public static void SaveNpcLS(Player player, uint npcLSId, bool isCalling, bool isExtra)
|
||||
{
|
||||
string query;
|
||||
MySqlCommand cmd;
|
||||
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
query = @"
|
||||
INSERT INTO characters_npclinkshell
|
||||
(characterId, npcLinkshellId, isCalling, isExtra)
|
||||
VALUES
|
||||
(@charaId, @lsId, @calling, @extra)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
characterId = @charaId, npcLinkshellId = @lsId, isCalling = @calling, isExtra = @extra
|
||||
";
|
||||
|
||||
cmd = new MySqlCommand(query, conn);
|
||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||
cmd.Parameters.AddWithValue("@lsId", npcLSId);
|
||||
cmd.Parameters.AddWithValue("@calling", isCalling ? 1 : 0);
|
||||
cmd.Parameters.AddWithValue("@extra", isExtra ? 1 : 0);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch (MySqlException e)
|
||||
{
|
||||
Program.Log.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool SaveSupportTicket(GMSupportTicketPacket gmTicket, string playerName)
|
||||
{
|
||||
|
@ -1556,4 +1925,5 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Cyotek.Collections.Generic.CircularBuffer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
|
||||
|
@ -73,6 +76,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="actors\area\PrivateArea.cs" />
|
||||
<Compile Include="actors\area\PrivateAreaContent.cs" />
|
||||
<Compile Include="actors\area\SpawnLocation.cs" />
|
||||
<Compile Include="actors\area\Zone.cs" />
|
||||
<Compile Include="actors\chara\npc\ActorClass.cs" />
|
||||
|
@ -83,17 +87,28 @@
|
|||
<Compile Include="actors\chara\Work.cs" />
|
||||
<Compile Include="actors\debug\Debug.cs" />
|
||||
<Compile Include="actors\director\Director.cs" />
|
||||
<Compile Include="actors\director\OpeningDirector.cs" />
|
||||
<Compile Include="actors\director\quest\QuestDirectorMan0g001.cs" />
|
||||
<Compile Include="actors\director\quest\QuestDirectorMan0l001.cs" />
|
||||
<Compile Include="actors\director\quest\QuestDirectorMan0u001.cs" />
|
||||
<Compile Include="actors\director\WeatherDirector.cs" />
|
||||
<Compile Include="actors\director\GuildleveDirector.cs" />
|
||||
<Compile Include="actors\director\Work\GuildleveWork.cs" />
|
||||
<Compile Include="actors\EventList.cs" />
|
||||
<Compile Include="actors\group\GLContentGroup.cs" />
|
||||
<Compile Include="actors\group\ContentGroup.cs" />
|
||||
<Compile Include="actors\group\Work\ContentGroupWork.cs" />
|
||||
<Compile Include="actors\group\Work\GlobalTemp.cs" />
|
||||
<Compile Include="actors\group\Group.cs" />
|
||||
<Compile Include="actors\group\MonsterParty.cs" />
|
||||
<Compile Include="actors\group\Party.cs" />
|
||||
<Compile Include="actors\group\Relation.cs" />
|
||||
<Compile Include="actors\group\Work\GroupGlobalSave.cs" />
|
||||
<Compile Include="actors\group\Work\GroupGlobalTemp.cs" />
|
||||
<Compile Include="actors\group\Work\GroupMemberSave.cs" />
|
||||
<Compile Include="actors\group\Work\PartyWork.cs" />
|
||||
<Compile Include="actors\group\Work\RelationWork.cs" />
|
||||
<Compile Include="actors\judge\Judge.cs" />
|
||||
<Compile Include="actors\quest\Quest.cs" />
|
||||
<Compile Include="actors\StaticActors.cs" />
|
||||
<Compile Include="actors\world\WorldMaster.cs" />
|
||||
<Compile Include="ClientConnection.cs" />
|
||||
<Compile Include="dataobjects\GuildleveData.cs" />
|
||||
<Compile Include="dataobjects\ZoneConnection.cs" />
|
||||
<Compile Include="CommandProcessor.cs" />
|
||||
<Compile Include="ConfigConstants.cs" />
|
||||
<Compile Include="Database.cs" />
|
||||
|
@ -110,24 +125,21 @@
|
|||
<Compile Include="actors\chara\CharaWork.cs" />
|
||||
<Compile Include="actors\chara\ParameterSave.cs" />
|
||||
<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\Item.cs" />
|
||||
<Compile Include="dataobjects\Session.cs" />
|
||||
<Compile Include="dataobjects\ItemData.cs" />
|
||||
<Compile Include="dataobjects\RecruitmentDetails.cs" />
|
||||
<Compile Include="dataobjects\SeamlessBoundry.cs" />
|
||||
<Compile Include="dataobjects\SearchEntry.cs" />
|
||||
<Compile Include="lua\LuaEngine.cs" />
|
||||
<Compile Include="lua\LuaEvent.cs" />
|
||||
<Compile Include="lua\LuaParam.cs" />
|
||||
<Compile Include="lua\LuaNpc.cs" />
|
||||
<Compile Include="lua\LuaPlayer.cs" />
|
||||
<Compile Include="lua\LuaScript.cs" />
|
||||
<Compile Include="lua\LuaUtils.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" />
|
||||
<Compile Include="packets\receive\GroupCreatedPacket.cs" />
|
||||
<Compile Include="packets\receive\HandshakePacket.cs" />
|
||||
<Compile Include="packets\receive\LangaugeCodePacket.cs" />
|
||||
<Compile Include="packets\receive\ParameterDataRequestPacket.cs" />
|
||||
|
@ -143,63 +155,74 @@
|
|||
<Compile Include="packets\receive\supportdesk\GMSupportTicketPacket.cs" />
|
||||
<Compile Include="packets\receive\supportdesk\GMTicketIssuesRequestPacket.cs" />
|
||||
<Compile Include="packets\receive\_0x02ReceivePacket.cs" />
|
||||
<Compile Include="packets\receive\_0x07Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\ActorDoEmotePacket.cs" />
|
||||
<Compile Include="packets\send\Actor\ActorInstantiatePacket.cs" />
|
||||
<Compile Include="packets\send\Actor\ActorSpecialGraphicPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\BattleAction1Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\battle\BattleAction.cs" />
|
||||
<Compile Include="packets\send\Actor\battle\BattleActionX00Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\battle\BattleActionX18Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\battle\BattleActionX10Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\DeleteAllActorsPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetEventStatus.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetNoticeEventCondition.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetPushEventConditionWithTriggerBox.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetPushEventConditionWithFan.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetEmoteEventCondition.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetTalkEventCondition.cs" />
|
||||
<Compile Include="packets\send\Actor\events\SetPushEventConditionWithCircle.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX01Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX08Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX16Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX32Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX64Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX64Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX32Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX16Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryListX01Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryListX08Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryListX16Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryListX64Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryListX32Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\_0x132Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorIsZoningPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\battle\BattleActionX01Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX01Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryBeginChangePacket.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryEndChangePacket.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryItemEndPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventoryItemPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventorySetBeginPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\InventorySetEndPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX08Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\RemoveActorPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorIconPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorIdleAnimationPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorStatusPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\_0xFPacket.cs" />
|
||||
<Compile Include="packets\receive\ZoneInCompletePacket.cs" />
|
||||
<Compile Include="packets\send\actor\ActorDoEmotePacket.cs" />
|
||||
<Compile Include="packets\send\actor\ActorInstantiatePacket.cs" />
|
||||
<Compile Include="packets\send\actor\ActorSpecialGraphicPacket.cs" />
|
||||
<Compile Include="packets\send\actor\battle\BattleAction.cs" />
|
||||
<Compile Include="packets\send\actor\battle\BattleActionX00Packet.cs" />
|
||||
<Compile Include="packets\send\actor\battle\BattleActionX18Packet.cs" />
|
||||
<Compile Include="packets\send\actor\battle\BattleActionX10Packet.cs" />
|
||||
<Compile Include="packets\send\actor\DeleteAllActorsPacket.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetEventStatus.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetNoticeEventCondition.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetPushEventConditionWithTriggerBox.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetPushEventConditionWithFan.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetEmoteEventCondition.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetTalkEventCondition.cs" />
|
||||
<Compile Include="packets\send\actor\events\SetPushEventConditionWithCircle.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryRemoveX01Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryRemoveX08Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryRemoveX16Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryRemoveX32Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryRemoveX64Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\EquipmentListX64Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\EquipmentListX32Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\EquipmentListX16Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryListX01Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryListX08Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryListX16Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryListX64Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryListX32Packet.cs" />
|
||||
<Compile Include="packets\send\actor\PlayAnimationOnActorPacket.cs" />
|
||||
<Compile Include="packets\send\actor\PlayBGAnimation.cs" />
|
||||
<Compile Include="packets\send\actor\_0x132Packet.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorIsZoningPacket.cs" />
|
||||
<Compile Include="packets\send\actor\battle\BattleActionX01Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\EquipmentListX01Packet.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryBeginChangePacket.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryEndChangePacket.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryItemEndPacket.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventoryItemPacket.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventorySetBeginPacket.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\InventorySetEndPacket.cs" />
|
||||
<Compile Include="packets\send\actor\inventory\EquipmentListX08Packet.cs" />
|
||||
<Compile Include="packets\send\actor\RemoveActorPacket.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorIconPacket.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorSubStatPacket.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorStatusPacket.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorBGPropertiesPacket.cs" />
|
||||
<Compile Include="packets\send\actor\_0xFPacket.cs" />
|
||||
<Compile Include="packets\send\groups\CreateNamedGroup.cs" />
|
||||
<Compile Include="packets\send\groups\CreateNamedGroupMultiple.cs" />
|
||||
<Compile Include="packets\send\events\EndEventPacket.cs" />
|
||||
<Compile Include="packets\send\events\KickEventPacket.cs" />
|
||||
<Compile Include="packets\send\events\RunEventFunctionPacket.cs" />
|
||||
<Compile Include="packets\send\GameMessagePacket.cs" />
|
||||
<Compile Include="packets\send\list\ListEntry.cs" />
|
||||
<Compile Include="packets\send\list\ListUtils.cs" />
|
||||
<Compile Include="packets\send\list\SetListPropertyPacket.cs" />
|
||||
<Compile Include="packets\send\list\ListBeginPacket.cs" />
|
||||
<Compile Include="packets\send\list\ListEndPacket.cs" />
|
||||
<Compile Include="packets\send\list\ListEntriesEndPacket.cs" />
|
||||
<Compile Include="packets\send\list\ListStartPacket.cs" />
|
||||
<Compile Include="packets\send\groups\DeleteGroupPacket.cs" />
|
||||
<Compile Include="packets\send\groups\GroupHeaderPacket.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMember.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMembersBeginPacket.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMembersEndPacket.cs" />
|
||||
<Compile Include="packets\send\groups\ContentMembersX08Packet.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMembersX08Packet.cs" />
|
||||
<Compile Include="packets\send\groups\ContentMembersX16Packet.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMembersX16Packet.cs" />
|
||||
<Compile Include="packets\send\groups\ContentMembersX32Packet.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMembersX32Packet.cs" />
|
||||
<Compile Include="packets\send\groups\ContentMembersX64Packet.cs" />
|
||||
<Compile Include="packets\send\groups\GroupMembersX64Packet.cs" />
|
||||
<Compile Include="packets\send\groups\SynchGroupWorkValuesPacket.cs" />
|
||||
<Compile Include="packets\send\player\GenericDataPacket.cs" />
|
||||
<Compile Include="packets\send\player\SendAchievementRatePacket.cs" />
|
||||
<Compile Include="packets\send\player\SetCurrentJobPacket.cs" />
|
||||
|
@ -214,11 +237,10 @@
|
|||
<Compile Include="packets\send\Actor\SetActorTargetPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorStatusAllPacket.cs" />
|
||||
<Compile Include="packets\send\login\0x2Packet.cs" />
|
||||
<Compile Include="packets\send\Actor\AddActorPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\MoveActorToPositionPacket.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorAppearancePacket.cs" />
|
||||
<Compile Include="packets\send\Actor\SetActorPositionPacket.cs" />
|
||||
<Compile Include="packets\send\login\0x7ResponsePacket.cs" />
|
||||
<Compile Include="packets\send\actor\AddActorPacket.cs" />
|
||||
<Compile Include="packets\send\actor\MoveActorToPositionPacket.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorAppearancePacket.cs" />
|
||||
<Compile Include="packets\send\actor\SetActorPositionPacket.cs" />
|
||||
<Compile Include="packets\send\LogoutPacket.cs" />
|
||||
<Compile Include="packets\send\player\SetCompletedAchievementsPacket.cs" />
|
||||
<Compile Include="packets\send\player\AchievementEarnedPacket.cs" />
|
||||
|
@ -228,9 +250,10 @@
|
|||
<Compile Include="packets\send\player\SetHasGoobbuePacket.cs" />
|
||||
<Compile Include="packets\send\player\SetHasChocoboPacket.cs" />
|
||||
<Compile Include="packets\send\player\SetLatestAchievementsPacket.cs" />
|
||||
<Compile Include="packets\send\player\SetPlayerItemStoragePacket.cs" />
|
||||
<Compile Include="packets\send\player\SetPlayerDreamPacket.cs" />
|
||||
<Compile Include="packets\send\player\SetPlayerTitlePacket.cs" />
|
||||
<Compile Include="packets\send\player\_0x196Packet.cs" />
|
||||
<Compile Include="packets\send\player\SetSpecialEventWorkPacket.cs" />
|
||||
<Compile Include="packets\send\PongPacket.cs" />
|
||||
<Compile Include="packets\send\QuitPacket.cs" />
|
||||
<Compile Include="packets\send\recruitment\CurrentRecruitmentDetailsPacket.cs" />
|
||||
|
@ -258,12 +281,28 @@
|
|||
<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\PartySyncPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Receive\SessionEndPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\CreateLinkshellPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\DeleteLinkshellPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\LinkshellInviteCancelPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\LinkshellChangePacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\LinkshellRankChangePacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\ModifyLinkshellPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\GroupInviteResultPacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\LinkshellInvitePacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\PartyInvitePacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\LinkshellLeavePacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\PartyLeavePacket.cs" />
|
||||
<Compile Include="packets\WorldPackets\Send\Group\PartyModifyPacket.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" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
|
@ -286,6 +325,7 @@
|
|||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<Compile Include="packets\WorldPackets\Send\WorldRequestZoneChangePacket.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
|
@ -295,9 +335,12 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy "$(SolutionDir)data\map_config.ini" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d
|
||||
xcopy "$(SolutionDir)data\scripts" "$(SolutionDir)$(ProjectName)\$(OutDir)scripts\" /e /d /y /s
|
||||
xcopy "$(SolutionDir)data\staticactors.bin" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.packets;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -18,202 +18,128 @@ 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;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
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.sourceId);
|
||||
|
||||
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();
|
||||
|
||||
SessionBeginPacket beginSessionPacket = new SessionBeginPacket(subpacket.data);
|
||||
|
||||
session = mServer.AddSession(subpacket.header.sourceId);
|
||||
|
||||
if (!beginSessionPacket.isLogin)
|
||||
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);
|
||||
|
||||
session.QueuePacket(SessionEndConfirmPacket.BuildPacket(session, endSessionPacket.destinationZoneId));
|
||||
client.FlushQueuedSendPackets();
|
||||
break;
|
||||
//World Server - Party Synch
|
||||
case 0x1020:
|
||||
PartySyncPacket partySyncPacket = new PartySyncPacket(subpacket.data);
|
||||
Server.GetWorldManager().PartyMemberListRecieved(partySyncPacket);
|
||||
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();
|
||||
session.QueuePacket(PongPacket.BuildPacket(session.id, pingPacket.time));
|
||||
session.Ping();
|
||||
break;
|
||||
//Unknown
|
||||
case 0x0002:
|
||||
|
||||
subpacket.DebugPrintSubPacket();
|
||||
client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false);
|
||||
|
||||
Server.GetWorldManager().DoLogin(player.GetActor());
|
||||
|
||||
session.QueuePacket(_0x2Packet.BuildPacket(session.id));
|
||||
client.FlushQueuedSendPackets();
|
||||
|
||||
break;
|
||||
//Chat Received
|
||||
case 0x0003:
|
||||
ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data);
|
||||
Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
|
||||
subpacket.DebugPrintSubPacket();
|
||||
//Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
|
||||
|
||||
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);
|
||||
if (chatMessage.logType == SendMessagePacket.MESSAGE_TYPE_SAY || chatMessage.logType == SendMessagePacket.MESSAGE_TYPE_SHOUT)
|
||||
session.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(session.id, chatMessage.logType, session.GetActor().customDisplayName, chatMessage.message), false);
|
||||
|
||||
break;
|
||||
//Langauge Code
|
||||
//Langauge Code (Client safe to send packets to now)
|
||||
case 0x0006:
|
||||
LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
|
||||
player.languageCode = langCode.languageCode;
|
||||
LuaEngine.GetInstance().CallLuaFunction(session.GetActor(), session.GetActor(), "onBeginLogin", true);
|
||||
Server.GetWorldManager().DoZoneIn(session.GetActor(), true, 0x1);
|
||||
LuaEngine.GetInstance().CallLuaFunction(session.GetActor(), session.GetActor(), "onLogin", true);
|
||||
session.languageCode = langCode.languageCode;
|
||||
break;
|
||||
//Unknown - Happens a lot at login, then once every time player zones
|
||||
case 0x0007:
|
||||
//subpacket.DebugPrintSubPacket();
|
||||
_0x07Packet unknown07 = new _0x07Packet(subpacket.data);
|
||||
ZoneInCompletePacket zoneInCompletePacket = new ZoneInCompletePacket(subpacket.data);
|
||||
break;
|
||||
//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 +147,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, 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 +176,20 @@ 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 = session.GetActor().zone.FindActorInArea(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;
|
||||
Director director = session.GetActor().GetDirector(eventStart.scriptOwnerActorID);
|
||||
if (director != null)
|
||||
ownerActor = director;
|
||||
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,12 +198,13 @@ 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;
|
||||
//Unknown, happens at npc spawn and cutscene play????
|
||||
case 0x00CE:
|
||||
subpacket.DebugPrintSubPacket();
|
||||
break;
|
||||
//Event Result
|
||||
case 0x012E:
|
||||
|
@ -285,42 +213,47 @@ 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();
|
||||
subpacket.DebugPrintSubPacket();
|
||||
ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
|
||||
if (paramRequest.paramName.Equals("charaWork/exp"))
|
||||
player.GetActor().SendCharaExpInfo();
|
||||
session.GetActor().SendCharaExpInfo();
|
||||
break;
|
||||
//Group Created Confirm
|
||||
case 0x0133:
|
||||
GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data);
|
||||
Server.GetWorldManager().SendGroupInit(session, groupCreated.groupId);
|
||||
break;
|
||||
/* RECRUITMENT */
|
||||
//Start Recruiting
|
||||
case 0x01C3:
|
||||
StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
|
||||
client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false));
|
||||
session.QueuePacket(StartRecruitingResponse.BuildPacket(session.id, true));
|
||||
break;
|
||||
//End Recruiting
|
||||
case 0x01C4:
|
||||
client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false));
|
||||
session.QueuePacket(EndRecruitmentPacket.BuildPacket(session.id));
|
||||
break;
|
||||
//Party Window Opened, Request State
|
||||
case 0x01C5:
|
||||
client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(player.actorID, true, true, 1), true, false));
|
||||
session.QueuePacket(RecruiterStatePacket.BuildPacket(session.id, false, false, 0));
|
||||
break;
|
||||
//Search Recruiting
|
||||
case 0x01C7:
|
||||
|
@ -336,7 +269,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));
|
||||
session.QueuePacket(CurrentRecruitmentDetailsPacket.BuildPacket(session.id, details));
|
||||
break;
|
||||
//Accepted Recruiting
|
||||
case 0x01C6:
|
||||
|
@ -345,81 +278,73 @@ 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));
|
||||
session.QueuePacket(BlacklistAddedPacket.BuildPacket(session.id, true, addBlackList.name));
|
||||
break;
|
||||
case 0x01CA:
|
||||
AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data);
|
||||
client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(player.actorID, true, RemoveBlackList.name), true, false));
|
||||
session.QueuePacket(BlacklistRemovedPacket.BuildPacket(session.id, true, RemoveBlackList.name));
|
||||
break;
|
||||
case 0x01CB:
|
||||
int offset1 = 0;
|
||||
client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(player.actorID, new String[] { "Test" }, ref offset1), true, false));
|
||||
session.QueuePacket(SendBlacklistPacket.BuildPacket(session.id, new String[] { "Test" }, ref offset1));
|
||||
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));
|
||||
session.QueuePacket(FriendlistAddedPacket.BuildPacket(session.id, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name));
|
||||
break;
|
||||
case 0x01CD:
|
||||
AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
|
||||
client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false));
|
||||
session.QueuePacket(FriendlistRemovedPacket.BuildPacket(session.id, true, RemoveFriendList.name));
|
||||
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));
|
||||
session.QueuePacket(SendFriendlistPacket.BuildPacket(session.id, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2));
|
||||
break;
|
||||
case 0x01CF:
|
||||
client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(player.actorID, null), true, false));
|
||||
session.QueuePacket(FriendStatusPacket.BuildPacket(session.id, null));
|
||||
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, Database.getFAQNames(faqRequest.langCode)), true, false));
|
||||
session.QueuePacket(FaqListResponsePacket.BuildPacket(session.id, new string[] { "Testing FAQ1", "Coded style!" }));
|
||||
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, Database.getFAQBody(faqBodyRequest.faqIndex, faqBodyRequest.langCode)), true, false));
|
||||
session.QueuePacket(FaqBodyResponsePacket.BuildPacket(session.id, "HERE IS A GIANT BODY. Nothing else to say!"));
|
||||
break;
|
||||
//Request issue list
|
||||
case 0x01D2:
|
||||
GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
|
||||
client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, Database.getIssues(issuesRequest.langCode)), true, false));
|
||||
session.QueuePacket(IssueListResponsePacket.BuildPacket(session.id, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }));
|
||||
break;
|
||||
//Request if GM ticket exists
|
||||
case 0x01D3:
|
||||
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, Database.isTicketOpen(player.GetActor().customDisplayName)), true, false));
|
||||
session.QueuePacket(StartGMTicketPacket.BuildPacket(session.id, false));
|
||||
break;
|
||||
//Request for GM response message
|
||||
case 0x01D4:
|
||||
client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "Ticket Title", "Enter your Help request here."), true, false));
|
||||
session.QueuePacket(GMTicketPacket.BuildPacket(session.id, "This is a GM Ticket Title", "This is a GM Ticket Body."));
|
||||
break;
|
||||
//GM Ticket Sent
|
||||
case 0x01D5:
|
||||
GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
|
||||
Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
|
||||
bool wasError = Database.SaveSupportTicket(gmTicket, player.GetActor().customDisplayName);
|
||||
client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, !wasError), true, false));
|
||||
|
||||
if (!wasError)
|
||||
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, true), true, false));
|
||||
|
||||
session.QueuePacket(GMTicketSentResponsePacket.BuildPacket(session.id, true));
|
||||
break;
|
||||
//Request to end ticket
|
||||
case 0x01D6:
|
||||
Database.closeTicket(player.GetActor().customDisplayName);
|
||||
client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false));
|
||||
session.QueuePacket(EndGMTicketPacket.BuildPacket(session.id));
|
||||
break;
|
||||
default:
|
||||
Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
|
||||
subpacket.DebugPrintSubPacket();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
packet.DebugPrintPacket();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
|
||||
// set up logging
|
||||
Log = LogManager.GetCurrentClassLogger();
|
||||
#if DEBUG
|
||||
|
@ -28,11 +27,14 @@ namespace FFXIVClassic_Map_Server
|
|||
#endif
|
||||
bool startServer = true;
|
||||
|
||||
Program.Log.Info("---------FFXIV 1.0 Map Server---------");
|
||||
Log.Info("==================================");
|
||||
Log.Info("FFXIV Classic Map Server");
|
||||
Log.Info("Version: 0.1");
|
||||
Log.Info("==================================");
|
||||
|
||||
//Load Config
|
||||
if (!ConfigConstants.Load())
|
||||
startServer = false;
|
||||
ConfigConstants.Load();
|
||||
ConfigConstants.ApplyLaunchArgs(args);
|
||||
|
||||
//Test DB Connection
|
||||
Program.Log.Info("Testing DB connection... ");
|
||||
|
@ -52,25 +54,18 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
}
|
||||
|
||||
//Check World ID
|
||||
DBWorld thisWorld = Database.GetServer(ConfigConstants.DATABASE_WORLDID);
|
||||
if (thisWorld != null)
|
||||
Program.Log.Info("Successfully pulled world info from DB. Server name is {0}.", thisWorld.name);
|
||||
else
|
||||
Program.Log.Info("World info could not be retrieved from the DB. Welcome and MOTD will not be displayed.");
|
||||
|
||||
//Start server if A-OK
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,30 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
private Socket mServerSocket;
|
||||
|
||||
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint, ConnectedPlayer>();
|
||||
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
|
||||
private LuaEngine mLuaEngine = new LuaEngine();
|
||||
private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();
|
||||
|
||||
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, ItemData> mGamedataItems;
|
||||
private static Dictionary<uint, GuildleveData> mGamedataGuildleves;
|
||||
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);
|
||||
mGamedataGuildleves = Database.GetGuildleveGamedata();
|
||||
Program.Log.Info("Loaded {0} guildleves.", mGamedataGuildleves.Count);
|
||||
|
||||
mWorldManager = new WorldManager(this);
|
||||
mWorldManager.LoadZoneList();
|
||||
|
@ -87,12 +54,13 @@ namespace FFXIVClassic_Map_Server
|
|||
mWorldManager.LoadActorClasses();
|
||||
mWorldManager.LoadSpawnLocations();
|
||||
mWorldManager.SpawnAllActors();
|
||||
mWorldManager.StartZoneThread();
|
||||
|
||||
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 +88,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 +165,7 @@ namespace FFXIVClassic_Map_Server
|
|||
{
|
||||
if (conn != null)
|
||||
{
|
||||
|
||||
lock (mConnectionList)
|
||||
{
|
||||
mConnectionList.Remove(conn);
|
||||
}
|
||||
mWorldConnection = null;
|
||||
}
|
||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||
}
|
||||
|
@ -176,53 +173,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 +207,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 +234,71 @@ 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()
|
||||
public static Dictionary<uint, ItemData> GetGamedataItems()
|
||||
{
|
||||
return mConnectedPlayerList;
|
||||
return mGamedataItems;
|
||||
}
|
||||
|
||||
public static Dictionary<uint, Item> GetGamedataItems()
|
||||
public static Actor GetStaticActors(uint id)
|
||||
{
|
||||
return gamedataItems;
|
||||
return mStaticActors.GetActor(id);
|
||||
}
|
||||
|
||||
public static Actor GetStaticActors(string name)
|
||||
{
|
||||
return mStaticActors.FindStaticActor(name);
|
||||
}
|
||||
|
||||
public static ItemData GetItemGamedata(uint id)
|
||||
{
|
||||
if (mGamedataItems.ContainsKey(id))
|
||||
return mGamedataItems[id];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GuildleveData GetGuildleveGamedata(uint id)
|
||||
{
|
||||
if (mGamedataGuildleves.ContainsKey(id))
|
||||
return mGamedataGuildleves[id];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,13 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using FFXIVClassic_Map_Server.packets.WorldPackets.Receive;
|
||||
using FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
namespace FFXIVClassic_Map_Server
|
||||
{
|
||||
|
@ -27,9 +34,18 @@ namespace FFXIVClassic_Map_Server
|
|||
private Dictionary<uint, List<SeamlessBoundry>> seamlessBoundryList;
|
||||
private Dictionary<uint, ZoneEntrance> zoneEntranceList;
|
||||
private Dictionary<uint, ActorClass> actorClasses = new Dictionary<uint,ActorClass>();
|
||||
private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object
|
||||
|
||||
private Server mServer;
|
||||
|
||||
private const int MILIS_LOOPTIME = 10;
|
||||
private Timer mZoneTimer;
|
||||
|
||||
//Content Groups
|
||||
public Dictionary<ulong, Group> mContentGroups = new Dictionary<ulong, Group>();
|
||||
private Object groupLock = new Object();
|
||||
public ulong groupIndexId = 1;
|
||||
|
||||
public WorldManager(Server server)
|
||||
{
|
||||
mServer = server;
|
||||
|
@ -52,7 +68,7 @@ namespace FFXIVClassic_Map_Server
|
|||
id,
|
||||
zoneName,
|
||||
regionId,
|
||||
className,
|
||||
classPath,
|
||||
dayMusic,
|
||||
nightMusic,
|
||||
battleMusic,
|
||||
|
@ -62,10 +78,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())
|
||||
|
@ -95,6 +114,7 @@ namespace FFXIVClassic_Map_Server
|
|||
id,
|
||||
parentZoneId,
|
||||
privateAreaName,
|
||||
privateAreaType,
|
||||
className,
|
||||
dayMusic,
|
||||
nightMusic,
|
||||
|
@ -113,7 +133,7 @@ namespace FFXIVClassic_Map_Server
|
|||
if (zoneList.ContainsKey(parentZoneId))
|
||||
{
|
||||
Zone parent = zoneList[parentZoneId];
|
||||
PrivateArea privArea = new PrivateArea(parent, reader.GetUInt32("id"), reader.GetString("className"), reader.GetString("privateAreaName"), 1, reader.GetUInt16("dayMusic"), reader.GetUInt16("nightMusic"), reader.GetUInt16("battleMusic"));
|
||||
PrivateArea privArea = new PrivateArea(parent, reader.GetUInt32("id"), reader.GetString("className"), reader.GetString("privateAreaName"), reader.GetUInt32("privateAreaType"), reader.GetUInt16("dayMusic"), reader.GetUInt16("nightMusic"), reader.GetUInt16("battleMusic"));
|
||||
parent.AddPrivateArea(privArea);
|
||||
}
|
||||
else
|
||||
|
@ -168,7 +188,7 @@ namespace FFXIVClassic_Map_Server
|
|||
if (!reader.IsDBNull(7))
|
||||
privArea = reader.GetString(7);
|
||||
|
||||
ZoneEntrance entance = new ZoneEntrance(reader.GetUInt32(1), privArea, reader.GetByte(2), reader.GetFloat(3), reader.GetFloat(4), reader.GetFloat(5), reader.GetFloat(6));
|
||||
ZoneEntrance entance = new ZoneEntrance(reader.GetUInt32(1), privArea, 1, reader.GetByte(2), reader.GetFloat(3), reader.GetFloat(4), reader.GetFloat(5), reader.GetFloat(6));
|
||||
zoneEntranceList[id] = entance;
|
||||
count++;
|
||||
}
|
||||
|
@ -257,12 +277,17 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
string query = @"
|
||||
SELECT
|
||||
id,
|
||||
gamedata_actor_class.id,
|
||||
classPath,
|
||||
displayNameId,
|
||||
propertyFlags,
|
||||
eventConditions
|
||||
eventConditions,
|
||||
pushCommand,
|
||||
pushCommandSub,
|
||||
pushCommandPriority
|
||||
FROM gamedata_actor_class
|
||||
LEFT JOIN gamedata_actor_pushcommand
|
||||
ON gamedata_actor_class.id = gamedata_actor_pushcommand.id
|
||||
WHERE classPath <> ''
|
||||
";
|
||||
|
||||
|
@ -284,7 +309,18 @@ namespace FFXIVClassic_Map_Server
|
|||
else
|
||||
eventConditions = "{}";
|
||||
|
||||
ActorClass actorClass = new ActorClass(id, classPath, nameId, propertyFlags, eventConditions);
|
||||
ushort pushCommand = 0;
|
||||
ushort pushCommandSub = 0;
|
||||
byte pushCommandPriority = 0;
|
||||
|
||||
if (!reader.IsDBNull(reader.GetOrdinal("pushCommand")))
|
||||
{
|
||||
pushCommand = reader.GetUInt16("pushCommand");
|
||||
pushCommandSub = reader.GetUInt16("pushCommandSub");
|
||||
pushCommandPriority = reader.GetByte("pushCommandPriority");
|
||||
}
|
||||
|
||||
ActorClass actorClass = new ActorClass(id, classPath, nameId, propertyFlags, eventConditions, pushCommand, pushCommandSub, pushCommandPriority);
|
||||
actorClasses.Add(id, actorClass);
|
||||
count++;
|
||||
}
|
||||
|
@ -334,13 +370,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 +393,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);
|
||||
|
@ -416,7 +450,7 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
player.SendMessage(0x20, "", "Doing Seamless Zone Change");
|
||||
|
||||
LuaEngine.OnZoneIn(player);
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, newZone, "onZoneIn", true);
|
||||
}
|
||||
|
||||
//Adds a second zone to pull actors from. Used for an improved seamless zone change.
|
||||
|
@ -436,7 +470,7 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
player.SendMessage(0x20, "", "Merging Zones");
|
||||
|
||||
LuaEngine.OnZoneIn(player);
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, mergedZone, "onZoneIn", true);
|
||||
}
|
||||
|
||||
//Checks all seamless bounding boxes in region to see if player needs to merge or zonechange
|
||||
|
@ -518,12 +552,30 @@ namespace FFXIVClassic_Map_Server
|
|||
}
|
||||
|
||||
ZoneEntrance ze = zoneEntranceList[zoneEntrance];
|
||||
DoZoneChange(player, ze.zoneId, ze.privateAreaName, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation);
|
||||
DoZoneChange(player, ze.zoneId, ze.privateAreaName, ze.privateAreaType, ze.spawnType, ze.spawnX, ze.spawnY, ze.spawnZ, ze.spawnRotation);
|
||||
}
|
||||
|
||||
//Moves actor to new zone, and sends packets to spawn at the given coords.
|
||||
public void DoZoneChange(Player player, uint destinationZoneId, string destinationPrivateArea, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
|
||||
public void DoZoneChange(Player player, uint destinationZoneId, string destinationPrivateArea, int destinationPrivateAreaType, byte spawnType, float spawnX, float spawnY, float spawnZ, float spawnRotation)
|
||||
{
|
||||
//Add player to new zone and update
|
||||
Area newArea;
|
||||
|
||||
if (destinationPrivateArea == null)
|
||||
newArea = GetZone(destinationZoneId);
|
||||
else //Add check for -1 if it is a instance
|
||||
newArea = GetZone(destinationZoneId).GetPrivateArea(destinationPrivateArea, (uint)destinationPrivateAreaType);
|
||||
|
||||
//This server does not contain that zoneId
|
||||
if (newArea == null)
|
||||
{
|
||||
Program.Log.Debug("Request to change to zone not on this server by: {0}.", player.customDisplayName);
|
||||
RequestWorldServerZoneChange(player, destinationZoneId, spawnType, spawnX, spawnY, spawnZ, spawnRotation);
|
||||
return;
|
||||
}
|
||||
|
||||
player.playerSession.LockUpdates(true);
|
||||
|
||||
Area oldZone = player.zone;
|
||||
//Remove player from currentZone if transfer else it's login
|
||||
if (player.zone != null)
|
||||
|
@ -531,46 +583,48 @@ namespace FFXIVClassic_Map_Server
|
|||
oldZone.RemoveActorFromZone(player);
|
||||
}
|
||||
|
||||
//Add player to new zone and update
|
||||
Area newArea;
|
||||
|
||||
if (destinationPrivateArea == null)
|
||||
newArea = GetZone(destinationZoneId);
|
||||
else
|
||||
newArea = GetZone(destinationZoneId).GetPrivateArea(destinationPrivateArea, 0);
|
||||
|
||||
//This server does not contain that zoneId
|
||||
if (newArea == null)
|
||||
{
|
||||
if (oldZone != null)
|
||||
{
|
||||
oldZone.AddActorToZone(player);
|
||||
}
|
||||
|
||||
var message = "WorldManager.DoZoneChange: unable to change areas, new area is not valid.";
|
||||
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM, "[Debug]", message);
|
||||
Program.Log.Debug(message);
|
||||
return;
|
||||
}
|
||||
|
||||
newArea.AddActorToZone(player);
|
||||
|
||||
//Update player actor's properties
|
||||
player.zoneId = newArea.actorId;
|
||||
player.zoneId = newArea is PrivateArea ? ((PrivateArea)newArea).GetParentZone().actorId : newArea.actorId;
|
||||
|
||||
player.privateArea = newArea is PrivateArea ? ((PrivateArea)newArea).GetPrivateAreaName() : null;
|
||||
player.privateAreaType = newArea is PrivateArea ? ((PrivateArea)newArea).GetPrivateAreaType() : 0;
|
||||
player.zone = newArea;
|
||||
player.positionX = spawnX;
|
||||
player.positionY = spawnY;
|
||||
player.positionZ = spawnZ;
|
||||
player.rotation = spawnRotation;
|
||||
|
||||
//Delete any GL directors
|
||||
GuildleveDirector glDirector = player.GetGuildleveDirector();
|
||||
if (glDirector != null)
|
||||
player.RemoveDirector(glDirector);
|
||||
|
||||
//Delete content if have
|
||||
if (player.currentContentGroup != null)
|
||||
{
|
||||
player.currentContentGroup.RemoveMember(player.actorId);
|
||||
player.SetCurrentContentGroup(null);
|
||||
|
||||
if (oldZone is PrivateAreaContent)
|
||||
((PrivateAreaContent)oldZone).CheckDestroy();
|
||||
}
|
||||
|
||||
//Send packets
|
||||
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId), true, false);
|
||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x0), true, false);
|
||||
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId));
|
||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x2));
|
||||
player.SendZoneInPackets(this, spawnType);
|
||||
player.playerSession.ClearInstance();
|
||||
player.SendInstanceUpdate();
|
||||
|
||||
LuaEngine.OnZoneIn(player);
|
||||
player.playerSession.LockUpdates(false);
|
||||
|
||||
//Send "You have entered an instance" if it's a Private Area
|
||||
if (newArea is PrivateArea)
|
||||
player.SendGameMessage(GetActor(), 34108, 0x20);
|
||||
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, newArea, "onZoneIn", true);
|
||||
}
|
||||
|
||||
//Moves actor within zone to spawn position
|
||||
|
@ -596,6 +650,7 @@ namespace FFXIVClassic_Map_Server
|
|||
//Remove player from currentZone if transfer else it's login
|
||||
if (player.zone != null)
|
||||
{
|
||||
player.playerSession.LockUpdates(true);
|
||||
player.zone.RemoveActorFromZone(player);
|
||||
player.zone.AddActorToZone(player);
|
||||
|
||||
|
@ -606,35 +661,99 @@ namespace FFXIVClassic_Map_Server
|
|||
player.rotation = spawnRotation;
|
||||
|
||||
//Send packets
|
||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x0), true, false);
|
||||
player.playerSession.QueuePacket(player.CreateSpawnTeleportPacket(player.actorId, spawnType), true, false);
|
||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x10));
|
||||
player.playerSession.QueuePacket(player.CreateSpawnTeleportPacket(spawnType));
|
||||
|
||||
player.playerSession.LockUpdates(false);
|
||||
player.SendInstanceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//Moves actor to new zone, and sends packets to spawn at the given coords.
|
||||
public void DoZoneChangeContent(Player player, PrivateAreaContent contentArea, float spawnX, float spawnY, float spawnZ, float spawnRotation, ushort spawnType = SetActorPositionPacket.SPAWNTYPE_WARP_DUTY)
|
||||
{
|
||||
//Content area was null
|
||||
if (contentArea == null)
|
||||
{
|
||||
Program.Log.Debug("Request to change to content area not on this server by: {0}.", player.customDisplayName);
|
||||
return;
|
||||
}
|
||||
|
||||
player.playerSession.LockUpdates(true);
|
||||
|
||||
Area oldZone = player.zone;
|
||||
//Remove player from currentZone if transfer else it's login
|
||||
if (player.zone != null)
|
||||
{
|
||||
oldZone.RemoveActorFromZone(player);
|
||||
}
|
||||
|
||||
contentArea.AddActorToZone(player);
|
||||
|
||||
//Update player actor's properties
|
||||
player.zoneId = contentArea.GetParentZone().actorId;
|
||||
|
||||
player.privateArea = contentArea.GetPrivateAreaName();
|
||||
player.privateAreaType = contentArea.GetPrivateAreaType();
|
||||
player.zone = contentArea;
|
||||
player.positionX = spawnX;
|
||||
player.positionY = spawnY;
|
||||
player.positionZ = spawnZ;
|
||||
player.rotation = spawnRotation;
|
||||
|
||||
//Send "You have entered an instance" if it's a Private Area
|
||||
player.SendGameMessage(GetActor(), 34108, 0x20);
|
||||
|
||||
//Send packets
|
||||
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId));
|
||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x10));
|
||||
player.SendZoneInPackets(this, spawnType);
|
||||
player.playerSession.ClearInstance();
|
||||
player.SendInstanceUpdate();
|
||||
|
||||
}
|
||||
player.playerSession.LockUpdates(false);
|
||||
|
||||
|
||||
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, contentArea, "onZoneIn", true);
|
||||
}
|
||||
|
||||
//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);
|
||||
Area playerArea;
|
||||
if (player.privateArea != null)
|
||||
playerArea = GetPrivateArea(player.zoneId, player.privateArea, player.privateAreaType);
|
||||
else
|
||||
playerArea = GetZone(player.zoneId);
|
||||
|
||||
//This server does not contain that zoneId
|
||||
if (zone == null)
|
||||
if (playerArea == null)
|
||||
return;
|
||||
|
||||
//Set the current zone and add player
|
||||
player.zone = zone;
|
||||
player.zone = playerArea;
|
||||
|
||||
LuaEngine.OnBeginLogin(player);
|
||||
|
||||
zone.AddActorToZone(player);
|
||||
playerArea.AddActorToZone(player);
|
||||
|
||||
//Send packets
|
||||
player.SendZoneInPackets(this, 0x1);
|
||||
if (!isLogin)
|
||||
{
|
||||
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId));
|
||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x2));
|
||||
//player.SendZoneInPackets(this, spawnType);
|
||||
}
|
||||
|
||||
LuaEngine.OnLogin(player);
|
||||
LuaEngine.OnZoneIn(player);
|
||||
player.SendZoneInPackets(this, spawnType);
|
||||
|
||||
player.destinationZone = 0;
|
||||
player.destinationSpawnType = 0;
|
||||
Database.SavePlayerPosition(player);
|
||||
|
||||
player.playerSession.LockUpdates(false);
|
||||
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, playerArea, "onZoneIn", true);
|
||||
}
|
||||
|
||||
public void ReloadZone(uint zoneId)
|
||||
|
@ -648,14 +767,266 @@ namespace FFXIVClassic_Map_Server
|
|||
|
||||
}
|
||||
|
||||
public ContentGroup CreateContentGroup(Director director, params Actor[] actors)
|
||||
{
|
||||
if (director == null)
|
||||
return null;
|
||||
|
||||
lock (groupLock)
|
||||
{
|
||||
uint[] initialMembers = null;
|
||||
|
||||
if (actors != null)
|
||||
{
|
||||
initialMembers = new uint[actors.Length];
|
||||
for (int i = 0; i < actors.Length; i++)
|
||||
initialMembers[i] = actors[i].actorId;
|
||||
}
|
||||
|
||||
groupIndexId = groupIndexId | 0x3000000000000000;
|
||||
|
||||
ContentGroup contentGroup = new ContentGroup(groupIndexId, director, initialMembers);
|
||||
mContentGroups.Add(groupIndexId, contentGroup);
|
||||
groupIndexId++;
|
||||
if (initialMembers != null && initialMembers.Length != 0)
|
||||
contentGroup.SendAll();
|
||||
|
||||
return contentGroup;
|
||||
}
|
||||
}
|
||||
|
||||
public ContentGroup CreateContentGroup(Director director, List<Actor> actors)
|
||||
{
|
||||
if (director == null)
|
||||
return null;
|
||||
|
||||
lock (groupLock)
|
||||
{
|
||||
uint[] initialMembers = null;
|
||||
|
||||
if (actors != null)
|
||||
{
|
||||
initialMembers = new uint[actors.Count];
|
||||
for (int i = 0; i < actors.Count; i++)
|
||||
initialMembers[i] = actors[i].actorId;
|
||||
}
|
||||
|
||||
groupIndexId = groupIndexId | 0x3000000000000000;
|
||||
|
||||
ContentGroup contentGroup = new ContentGroup(groupIndexId, director, initialMembers);
|
||||
mContentGroups.Add(groupIndexId, contentGroup);
|
||||
groupIndexId++;
|
||||
if (initialMembers != null && initialMembers.Length != 0)
|
||||
contentGroup.SendAll();
|
||||
|
||||
return contentGroup;
|
||||
}
|
||||
}
|
||||
|
||||
public ContentGroup CreateGLContentGroup(Director director, List<Actor> actors)
|
||||
{
|
||||
if (director == null)
|
||||
return null;
|
||||
|
||||
lock (groupLock)
|
||||
{
|
||||
uint[] initialMembers = null;
|
||||
|
||||
if (actors != null)
|
||||
{
|
||||
initialMembers = new uint[actors.Count];
|
||||
for (int i = 0; i < actors.Count; i++)
|
||||
initialMembers[i] = actors[i].actorId;
|
||||
}
|
||||
|
||||
groupIndexId = groupIndexId | 0x2000000000000000;
|
||||
|
||||
GLContentGroup contentGroup = new GLContentGroup(groupIndexId, director, initialMembers);
|
||||
mContentGroups.Add(groupIndexId, contentGroup);
|
||||
groupIndexId++;
|
||||
if (initialMembers != null && initialMembers.Length != 0)
|
||||
contentGroup.SendAll();
|
||||
|
||||
return contentGroup;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteContentGroup(ulong groupId)
|
||||
{
|
||||
lock (groupLock)
|
||||
{
|
||||
if (mContentGroups.ContainsKey(groupId) && mContentGroups[groupId] is ContentGroup)
|
||||
{
|
||||
ContentGroup group = (ContentGroup)mContentGroups[groupId];
|
||||
mContentGroups.Remove(groupId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool SendGroupInit(Session session, ulong groupId)
|
||||
{
|
||||
if (mContentGroups.ContainsKey(groupId))
|
||||
{
|
||||
mContentGroups[groupId].SendInitWorkValues(session);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellCreate(Player player, string name, ushort crest)
|
||||
{
|
||||
SubPacket packet = CreateLinkshellPacket.BuildPacket(player.playerSession, name, crest, player.actorId);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellCrestModify(Player player, string name, ushort crest)
|
||||
{
|
||||
SubPacket packet = ModifyLinkshellPacket.BuildPacket(player.playerSession, 1, name, null, crest, 0);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellDelete(Player player, string name)
|
||||
{
|
||||
SubPacket packet = DeleteLinkshellPacket.BuildPacket(player.playerSession, name);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellRankChange(Player player, string lsname, string memberName, byte newRank)
|
||||
{
|
||||
SubPacket packet = LinkshellRankChangePacket.BuildPacket(player.playerSession, memberName, lsname, newRank);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellInviteMember(Player player, string lsname, uint invitedActorId)
|
||||
{
|
||||
SubPacket packet = LinkshellInvitePacket.BuildPacket(player.playerSession, invitedActorId, lsname);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellCancelInvite(Player player)
|
||||
{
|
||||
SubPacket packet = LinkshellInviteCancelPacket.BuildPacket(player.playerSession);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellLeave(Player player, string lsname)
|
||||
{
|
||||
SubPacket packet = LinkshellLeavePacket.BuildPacket(player.playerSession, lsname, null, false);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellKick(Player player, string lsname, string kickedName)
|
||||
{
|
||||
SubPacket packet = LinkshellLeavePacket.BuildPacket(player.playerSession, lsname, kickedName, true);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
public void RequestWorldLinkshellChangeActive(Player player, string lsname)
|
||||
{
|
||||
SubPacket packet = LinkshellChangePacket.BuildPacket(player.playerSession, lsname);
|
||||
player.QueuePacket(packet);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//World server sent a party member list synch packet to the zone server. Add and update players that may be a part of it.
|
||||
public void PartyMemberListRecieved(PartySyncPacket syncPacket)
|
||||
{
|
||||
lock (currentPlayerParties)
|
||||
{
|
||||
Party group;
|
||||
|
||||
//If no members on this server, get out or clean
|
||||
if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId) && syncPacket.memberActorIds.Length == 0)
|
||||
return;
|
||||
else if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId) && syncPacket.memberActorIds.Length == 0)
|
||||
NoMembersInParty(currentPlayerParties[syncPacket.partyGroupId]);
|
||||
|
||||
//Get or create group
|
||||
if (!currentPlayerParties.ContainsKey(syncPacket.partyGroupId))
|
||||
{
|
||||
group = new Party(syncPacket.partyGroupId, syncPacket.owner);
|
||||
currentPlayerParties.Add(syncPacket.partyGroupId, group);
|
||||
}
|
||||
else
|
||||
group = currentPlayerParties[syncPacket.partyGroupId];
|
||||
|
||||
group.SetLeader(syncPacket.owner);
|
||||
group.members = syncPacket.memberActorIds.ToList();
|
||||
|
||||
//Add group to everyone
|
||||
for (int i = 0; i < group.members.Count; i++ )
|
||||
{
|
||||
uint member = group.members[i];
|
||||
Session session = Server.GetServer().GetSession(member);
|
||||
|
||||
if (session == null)
|
||||
continue;
|
||||
|
||||
Player player = session.GetActor();
|
||||
if (player == null)
|
||||
continue;
|
||||
player.SetParty(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Player was removed from the party either due to leaving it or leaving the server. Remove if empty.
|
||||
public void NoMembersInParty(Party party)
|
||||
{
|
||||
if (currentPlayerParties.ContainsKey(party.groupIndex))
|
||||
currentPlayerParties.Remove(party.groupIndex);
|
||||
}
|
||||
|
||||
public void CreateInvitePartyGroup(Player player, string name)
|
||||
{
|
||||
SubPacket invitePacket = PartyInvitePacket.BuildPacket(player.playerSession, name);
|
||||
player.QueuePacket(invitePacket);
|
||||
}
|
||||
public void CreateInvitePartyGroup(Player player, uint actorId)
|
||||
{
|
||||
SubPacket invitePacket = PartyInvitePacket.BuildPacket(player.playerSession, actorId);
|
||||
player.QueuePacket(invitePacket);
|
||||
}
|
||||
|
||||
public void GroupInviteResult(Player player, uint groupType, uint result)
|
||||
{
|
||||
SubPacket groupInviteResultPacket = GroupInviteResultPacket.BuildPacket(player.playerSession, groupType, result);
|
||||
player.QueuePacket(groupInviteResultPacket);
|
||||
}
|
||||
|
||||
public void StartZoneThread()
|
||||
{
|
||||
mZoneTimer = new Timer(ZoneThreadLoop, null, 0, MILIS_LOOPTIME);
|
||||
Program.Log.Info("Zone Loop has started");
|
||||
}
|
||||
|
||||
public void ZoneThreadLoop(Object state)
|
||||
{
|
||||
lock (zoneList)
|
||||
{
|
||||
foreach (Area area in zoneList.Values)
|
||||
area.Update(MILIS_LOOPTIME);
|
||||
}
|
||||
}
|
||||
|
||||
public Player GetPCInWorld(string name)
|
||||
{
|
||||
foreach (Zone zone in zoneList.Values)
|
||||
{
|
||||
Player p = zone.FindPCInZone(name);
|
||||
if (p != null)
|
||||
return p;
|
||||
if (Server.GetServer().GetSession(name) != null)
|
||||
return Server.GetServer().GetSession(name).GetActor();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Player GetPCInWorld(uint charId)
|
||||
{
|
||||
if (Server.GetServer().GetSession(charId) != null)
|
||||
return Server.GetServer().GetSession(charId).GetActor();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -670,13 +1041,13 @@ namespace FFXIVClassic_Map_Server
|
|||
return null;
|
||||
}
|
||||
|
||||
public Player GetPCInWorld(uint charId)
|
||||
public Actor GetActorInWorldByUniqueId(string uid)
|
||||
{
|
||||
foreach (Zone zone in zoneList.Values)
|
||||
{
|
||||
Player p = zone.FindPCInZone(charId);
|
||||
if (p != null)
|
||||
return p;
|
||||
Actor a = zone.FindActorInZoneByUniqueID(uid);
|
||||
if (a != null)
|
||||
return a;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -688,6 +1059,14 @@ namespace FFXIVClassic_Map_Server
|
|||
return zoneList[zoneId];
|
||||
}
|
||||
|
||||
public PrivateArea GetPrivateArea(uint zoneId, string privateArea, uint privateAreaType)
|
||||
{
|
||||
if (!zoneList.ContainsKey(zoneId))
|
||||
return null;
|
||||
|
||||
return zoneList[zoneId].GetPrivateArea(privateArea, privateAreaType);
|
||||
}
|
||||
|
||||
public WorldMaster GetActor()
|
||||
{
|
||||
return worldMaster;
|
||||
|
@ -702,16 +1081,18 @@ namespace FFXIVClassic_Map_Server
|
|||
{
|
||||
public uint zoneId;
|
||||
public string privateAreaName;
|
||||
public int privateAreaType;
|
||||
public byte spawnType;
|
||||
public float spawnX;
|
||||
public float spawnY;
|
||||
public float spawnZ;
|
||||
public float spawnRotation;
|
||||
|
||||
public ZoneEntrance(uint zoneId, string privateAreaName, byte spawnType, float x, float y, float z, float rot)
|
||||
public ZoneEntrance(uint zoneId, string privateAreaName, int privateAreaType, byte spawnType, float x, float y, float z, float rot)
|
||||
{
|
||||
this.zoneId = zoneId;
|
||||
this.privateAreaName = privateAreaName;
|
||||
this.privateAreaType = privateAreaType;
|
||||
this.spawnType = spawnType;
|
||||
this.spawnX = x;
|
||||
this.spawnY = y;
|
||||
|
|
|
@ -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;
|
||||
|
@ -7,6 +7,9 @@ using FFXIVClassic.Common;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FFXIVClassic_Map_Server.actors.area;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor.battle;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
|
@ -23,9 +26,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public float positionX, positionY, positionZ, rotation;
|
||||
public float oldPositionX, oldPositionY, oldPositionZ, oldRotation;
|
||||
public ushort moveState, oldMoveState;
|
||||
public float[] moveSpeeds = new float[5];
|
||||
public float[] moveSpeeds = new float[4];
|
||||
|
||||
public uint zoneId, zoneId2;
|
||||
public string privateArea;
|
||||
public uint privateAreaType;
|
||||
public Area zone = null;
|
||||
public Area zone2 = null;
|
||||
public bool isZoning = false;
|
||||
|
@ -53,69 +58,91 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
this.moveSpeeds[0] = SetActorSpeedPacket.DEFAULT_STOP;
|
||||
this.moveSpeeds[1] = SetActorSpeedPacket.DEFAULT_WALK;
|
||||
this.moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN;
|
||||
this.moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_RUN;
|
||||
this.moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_ACTIVE;
|
||||
}
|
||||
|
||||
public SubPacket CreateAddActorPacket(uint playerActorId, byte val)
|
||||
public void SetPushCircleRange(string triggerName, float size)
|
||||
{
|
||||
return AddActorPacket.BuildPacket(actorId, playerActorId, val);
|
||||
if (eventConditions == null || eventConditions.pushWithCircleEventConditions == null)
|
||||
return;
|
||||
|
||||
foreach (EventList.PushCircleEventCondition condition in eventConditions.pushWithCircleEventConditions)
|
||||
{
|
||||
if (condition.conditionName.Equals(triggerName))
|
||||
{
|
||||
condition.radius = size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SubPacket CreateNamePacket(uint playerActorId)
|
||||
public SubPacket CreateAddActorPacket(byte val)
|
||||
{
|
||||
return SetActorNamePacket.BuildPacket(actorId, playerActorId, displayNameId, displayNameId == 0xFFFFFFFF | displayNameId == 0x0 ? customDisplayName : "");
|
||||
return AddActorPacket.BuildPacket(actorId, val);
|
||||
}
|
||||
|
||||
public SubPacket CreateSpeedPacket(uint playerActorId)
|
||||
public SubPacket CreateNamePacket()
|
||||
{
|
||||
return SetActorSpeedPacket.BuildPacket(actorId, playerActorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2]);
|
||||
return SetActorNamePacket.BuildPacket(actorId, displayNameId, displayNameId == 0xFFFFFFFF | displayNameId == 0x0 ? customDisplayName : "");
|
||||
}
|
||||
|
||||
public SubPacket CreateSpawnPositonPacket(uint playerActorId, uint spawnType)
|
||||
public SubPacket CreateSpeedPacket()
|
||||
{
|
||||
return SetActorSpeedPacket.BuildPacket(actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2], moveSpeeds[3]);
|
||||
}
|
||||
|
||||
public SubPacket CreateSpawnPositonPacket(ushort spawnType)
|
||||
{
|
||||
return CreateSpawnPositonPacket(null, spawnType);
|
||||
}
|
||||
|
||||
public SubPacket CreateSpawnPositonPacket(Player player, ushort spawnType)
|
||||
{
|
||||
//TODO: FIX THIS IF
|
||||
uint playerActorId = player == null ? 0 : player.actorId; //Get Rid
|
||||
SubPacket spawnPacket;
|
||||
if (!spawnedFirstTime && playerActorId == actorId)
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, 0, positionX, positionY, positionZ, rotation, 0x1, false);
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, 0, positionX, positionY, positionZ, rotation, 0x1, false);
|
||||
else if (playerActorId == actorId)
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, 0xFFFFFFFF, positionX, positionY, positionZ, rotation, spawnType, true);
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, 0xFFFFFFFF, positionX, positionY, positionZ, rotation, spawnType, true);
|
||||
else
|
||||
{
|
||||
if (this is Player)
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, 0, positionX, positionY, positionZ, rotation, spawnType, false);
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, 0, positionX, positionY, positionZ, rotation, spawnType, false);
|
||||
else
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, actorId, positionX, positionY, positionZ, rotation, spawnType, false);
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, actorId, positionX, positionY, positionZ, rotation, spawnType, false);
|
||||
}
|
||||
|
||||
//return SetActorPositionPacket.BuildPacket(actorId, playerActorId, -211.895477f, 190.000000f, 29.651011f, 2.674819f, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE);
|
||||
//return SetActorPositionPacket.BuildPacket(actorId, -211.895477f, 190.000000f, 29.651011f, 2.674819f, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE);
|
||||
spawnedFirstTime = true;
|
||||
|
||||
return spawnPacket;
|
||||
}
|
||||
|
||||
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, uint spawnType)
|
||||
public SubPacket CreateSpawnTeleportPacket(ushort spawnType)
|
||||
{
|
||||
SubPacket spawnPacket;
|
||||
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, playerActorId, 0xFFFFFFFF, positionX, positionY, positionZ, rotation, spawnType, false);
|
||||
spawnPacket = SetActorPositionPacket.BuildPacket(actorId, 0xFFFFFFFF, positionX, positionY, positionZ, rotation, spawnType, false);
|
||||
|
||||
//return SetActorPositionPacket.BuildPacket(actorId, playerActorId, -211.895477f, 190.000000f, 29.651011f, 2.674819f, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE);
|
||||
//return SetActorPositionPacket.BuildPacket(actorId, -211.895477f, 190.000000f, 29.651011f, 2.674819f, SetActorPositionPacket.SPAWNTYPE_PLAYERWAKE);
|
||||
|
||||
//spawnPacket.DebugPrintSubPacket();
|
||||
|
||||
return spawnPacket;
|
||||
}
|
||||
|
||||
public SubPacket CreatePositionUpdatePacket(uint playerActorId)
|
||||
public SubPacket CreatePositionUpdatePacket()
|
||||
{
|
||||
return MoveActorToPositionPacket.BuildPacket(actorId, playerActorId, positionX, positionY, positionZ, rotation, moveState);
|
||||
return MoveActorToPositionPacket.BuildPacket(actorId, positionX, positionY, positionZ, rotation, moveState);
|
||||
}
|
||||
|
||||
public SubPacket CreateStatePacket(uint playerActorID)
|
||||
public SubPacket CreateStatePacket()
|
||||
{
|
||||
return SetActorStatePacket.BuildPacket(actorId, playerActorID, currentMainState, currentSubState);
|
||||
return SetActorStatePacket.BuildPacket(actorId, currentMainState, currentSubState);
|
||||
}
|
||||
|
||||
public List<SubPacket> GetEventConditionPackets(uint playerActorId)
|
||||
public List<SubPacket> GetEventConditionPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
|
||||
|
@ -126,126 +153,147 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
if (eventConditions.talkEventConditions != null)
|
||||
{
|
||||
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
|
||||
subpackets.Add(SetTalkEventCondition.BuildPacket(playerActorId, actorId, condition));
|
||||
subpackets.Add(SetTalkEventCondition.BuildPacket(actorId, condition));
|
||||
}
|
||||
|
||||
if (eventConditions.noticeEventConditions != null)
|
||||
{
|
||||
foreach (EventList.NoticeEventCondition condition in eventConditions.noticeEventConditions)
|
||||
subpackets.Add(SetNoticeEventCondition.BuildPacket(playerActorId, actorId, condition));
|
||||
subpackets.Add(SetNoticeEventCondition.BuildPacket(actorId, condition));
|
||||
}
|
||||
|
||||
if (eventConditions.emoteEventConditions != null)
|
||||
{
|
||||
foreach (EventList.EmoteEventCondition condition in eventConditions.emoteEventConditions)
|
||||
subpackets.Add(SetEmoteEventCondition.BuildPacket(playerActorId, actorId, condition));
|
||||
subpackets.Add(SetEmoteEventCondition.BuildPacket(actorId, condition));
|
||||
}
|
||||
|
||||
if (eventConditions.pushWithCircleEventConditions != null)
|
||||
{
|
||||
foreach (EventList.PushCircleEventCondition condition in eventConditions.pushWithCircleEventConditions)
|
||||
subpackets.Add(SetPushEventConditionWithCircle.BuildPacket(playerActorId, actorId, condition));
|
||||
subpackets.Add(SetPushEventConditionWithCircle.BuildPacket(actorId, condition));
|
||||
}
|
||||
|
||||
if (eventConditions.pushWithFanEventConditions != null)
|
||||
{
|
||||
foreach (EventList.PushFanEventCondition condition in eventConditions.pushWithFanEventConditions)
|
||||
subpackets.Add(SetPushEventConditionWithFan.BuildPacket(playerActorId, actorId, condition));
|
||||
subpackets.Add(SetPushEventConditionWithFan.BuildPacket(actorId, condition));
|
||||
}
|
||||
|
||||
if (eventConditions.pushWithBoxEventConditions != null)
|
||||
{
|
||||
foreach (EventList.PushBoxEventCondition condition in eventConditions.pushWithBoxEventConditions)
|
||||
subpackets.Add(SetPushEventConditionWithTriggerBox.BuildPacket(playerActorId, actorId, condition));
|
||||
subpackets.Add(SetPushEventConditionWithTriggerBox.BuildPacket(actorId, condition));
|
||||
}
|
||||
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public BasePacket GetSetEventStatusPackets(uint playerActorId)
|
||||
public List<SubPacket> GetSetEventStatusPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
|
||||
//Return empty list
|
||||
if (eventConditions == null)
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
return subpackets;
|
||||
|
||||
if (eventConditions.talkEventConditions != null)
|
||||
{
|
||||
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
|
||||
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 1, condition.conditionName));
|
||||
subpackets.Add(SetEventStatus.BuildPacket(actorId, true, 1, condition.conditionName));
|
||||
}
|
||||
|
||||
if (eventConditions.noticeEventConditions != null)
|
||||
{
|
||||
foreach (EventList.NoticeEventCondition condition in eventConditions.noticeEventConditions)
|
||||
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 1, condition.conditionName));
|
||||
subpackets.Add(SetEventStatus.BuildPacket(actorId, true, 1, condition.conditionName));
|
||||
}
|
||||
|
||||
if (eventConditions.emoteEventConditions != null)
|
||||
{
|
||||
foreach (EventList.EmoteEventCondition condition in eventConditions.emoteEventConditions)
|
||||
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 3, condition.conditionName));
|
||||
subpackets.Add(SetEventStatus.BuildPacket(actorId, true, 3, condition.conditionName));
|
||||
}
|
||||
|
||||
if (eventConditions.pushWithCircleEventConditions != null)
|
||||
{
|
||||
foreach (EventList.PushCircleEventCondition condition in eventConditions.pushWithCircleEventConditions)
|
||||
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 2, condition.conditionName));
|
||||
subpackets.Add(SetEventStatus.BuildPacket(actorId, true, 2, condition.conditionName));
|
||||
}
|
||||
|
||||
if (eventConditions.pushWithFanEventConditions != null)
|
||||
{
|
||||
foreach (EventList.PushFanEventCondition condition in eventConditions.pushWithFanEventConditions)
|
||||
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 2, condition.conditionName));
|
||||
subpackets.Add(SetEventStatus.BuildPacket(actorId, true, 2, condition.conditionName));
|
||||
}
|
||||
|
||||
if (eventConditions.pushWithBoxEventConditions != null)
|
||||
{
|
||||
foreach (EventList.PushBoxEventCondition condition in eventConditions.pushWithBoxEventConditions)
|
||||
subpackets.Add(SetEventStatus.BuildPacket(playerActorId, actorId, true, 2, condition.conditionName));
|
||||
subpackets.Add(SetEventStatus.BuildPacket(actorId, true, 2, condition.conditionName));
|
||||
}
|
||||
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public SubPacket CreateIsZoneingPacket(uint playerActorId)
|
||||
public SubPacket CreateIsZoneingPacket()
|
||||
{
|
||||
return SetActorIsZoningPacket.BuildPacket(actorId, playerActorId, false);
|
||||
return SetActorIsZoningPacket.BuildPacket(actorId, false);
|
||||
}
|
||||
|
||||
public virtual SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public virtual SubPacket CreateScriptBindPacket(Player player)
|
||||
{
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, classParams);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, classParams);
|
||||
}
|
||||
|
||||
public virtual BasePacket GetSpawnPackets(uint playerActorId)
|
||||
public virtual SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
return GetSpawnPackets(playerActorId, 0x1);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, classParams);
|
||||
}
|
||||
|
||||
public virtual BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
|
||||
public virtual List<SubPacket> GetSpawnPackets(Player player, ushort spawnType)
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId, 8));
|
||||
subpackets.AddRange(GetEventConditionPackets(playerActorId));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, spawnType));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
subpackets.Add(CreateAddActorPacket(8));
|
||||
subpackets.AddRange(GetEventConditionPackets());
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(player, spawnType));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket(player));
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public virtual BasePacket GetInitPackets(uint playerActorId)
|
||||
public virtual List<SubPacket> GetSpawnPackets()
|
||||
{
|
||||
return GetSpawnPackets(0x1);
|
||||
}
|
||||
|
||||
public virtual List<SubPacket> GetSpawnPackets(ushort spawnType)
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(8));
|
||||
subpackets.AddRange(GetEventConditionPackets());
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(null, spawnType));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket());
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public virtual List<SubPacket> GetInitPackets()
|
||||
{
|
||||
List<SubPacket> packets = new List<SubPacket>();
|
||||
SetActorPropetyPacket initProperties = new SetActorPropetyPacket("/_init");
|
||||
initProperties.AddByte(0xE14B0CA8, 1);
|
||||
initProperties.AddByte(0x2138FD71, 1);
|
||||
initProperties.AddByte(0xFBFBCFB1, 1);
|
||||
initProperties.AddTarget();
|
||||
return BasePacket.CreatePacket(initProperties.BuildPacket(playerActorId, actorId), true, false);
|
||||
packets.Add(initProperties.BuildPacket(actorId));
|
||||
return packets;
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
|
@ -280,8 +328,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public void ChangeState(ushort newState)
|
||||
{
|
||||
currentMainState = newState;
|
||||
SubPacket ChangeStatePacket = SetActorStatePacket.BuildPacket(actorId, actorId, newState, currentSubState);
|
||||
SubPacket battleActionPacket = BattleAction1Packet.BuildPacket(actorId, actorId);
|
||||
SubPacket ChangeStatePacket = SetActorStatePacket.BuildPacket(actorId, newState, currentSubState);
|
||||
SubPacket battleActionPacket = BattleActionX01Packet.BuildPacket(actorId, actorId, actorId, 0x72000062, 1, 0, 0x05209, 0, 0);
|
||||
zone.BroadcastPacketAroundActor(this, ChangeStatePacket);
|
||||
zone.BroadcastPacketAroundActor(this, battleActionPacket);
|
||||
}
|
||||
|
@ -289,20 +337,24 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public void ChangeSpeed(int type, float value)
|
||||
{
|
||||
moveSpeeds[type] = value;
|
||||
SubPacket ChangeSpeedPacket = SetActorSpeedPacket.BuildPacket(actorId, actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2]);
|
||||
SubPacket ChangeSpeedPacket = SetActorSpeedPacket.BuildPacket(actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2], moveSpeeds[3]);
|
||||
zone.BroadcastPacketAroundActor(this, ChangeSpeedPacket);
|
||||
}
|
||||
|
||||
public void ChangeSpeed(float speedStop, float speedWalk, float speedRun)
|
||||
public void ChangeSpeed(float speedStop, float speedWalk, float speedRun, float speedActive)
|
||||
{
|
||||
moveSpeeds[0] = speedStop;
|
||||
moveSpeeds[1] = speedWalk;
|
||||
moveSpeeds[2] = speedRun;
|
||||
moveSpeeds[3] = speedRun;
|
||||
SubPacket ChangeSpeedPacket = SetActorSpeedPacket.BuildPacket(actorId, actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2]);
|
||||
moveSpeeds[3] = speedActive;
|
||||
SubPacket ChangeSpeedPacket = SetActorSpeedPacket.BuildPacket(actorId, moveSpeeds[0], moveSpeeds[1], moveSpeeds[2], moveSpeeds[3]);
|
||||
zone.BroadcastPacketAroundActor(this, ChangeSpeedPacket);
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
public void GenerateActorName(int actorNumber)
|
||||
{
|
||||
//Format Class Name
|
||||
|
@ -345,11 +397,92 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
uint zoneId = zone.actorId;
|
||||
uint privLevel = 0;
|
||||
if (zone is PrivateArea)
|
||||
privLevel = ((PrivateArea)zone).GetPrivateAreaLevel();
|
||||
privLevel = ((PrivateArea)zone).GetPrivateAreaType();
|
||||
|
||||
actorName = String.Format("{0}_{1}_{2}@{3:X3}{4:X2}", className, zoneName, classNumber, zoneId, privLevel);
|
||||
}
|
||||
|
||||
public bool SetWorkValue(Player player, string name, string uiFunc, object value)
|
||||
{
|
||||
string[] split = name.Split('.');
|
||||
int arrayIndex = 0;
|
||||
|
||||
if (!(split[0].Equals("work") || split[0].Equals("charaWork") || split[0].Equals("playerWork") || split[0].Equals("npcWork")))
|
||||
return false;
|
||||
|
||||
Object parentObj = null;
|
||||
Object curObj = this;
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
//For arrays
|
||||
if (split[i].Contains("["))
|
||||
{
|
||||
if (split[i].LastIndexOf(']') - split[i].IndexOf('[') <= 0)
|
||||
return false;
|
||||
|
||||
arrayIndex = Convert.ToInt32(split[i].Substring(split[i].IndexOf('[') + 1, split[i].LastIndexOf(']') - split[i].LastIndexOf('[') - 1));
|
||||
split[i] = split[i].Substring(0, split[i].IndexOf('['));
|
||||
}
|
||||
|
||||
FieldInfo field = curObj.GetType().GetField(split[i]);
|
||||
if (field == null)
|
||||
return false;
|
||||
|
||||
if (i == split.Length - 1)
|
||||
parentObj = curObj;
|
||||
curObj = field.GetValue(curObj);
|
||||
if (curObj == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (curObj == null)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
//Array, we actually care whats inside
|
||||
if (curObj.GetType().IsArray)
|
||||
{
|
||||
if (((Array)curObj).Length <= arrayIndex)
|
||||
return false;
|
||||
|
||||
if (value.GetType() == ((Array)curObj).GetType().GetElementType() || TypeDescriptor.GetConverter(value.GetType()).CanConvertTo(((Array)curObj).GetType().GetElementType()))
|
||||
{
|
||||
if (value.GetType() == ((Array)curObj).GetType().GetElementType())
|
||||
((Array)curObj).SetValue(value, arrayIndex);
|
||||
else
|
||||
((Array)curObj).SetValue(TypeDescriptor.GetConverter(value.GetType()).ConvertTo(value, curObj.GetType().GetElementType()), arrayIndex);
|
||||
|
||||
SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(uiFunc);
|
||||
changeProperty.AddProperty(this, name);
|
||||
changeProperty.AddTarget();
|
||||
SubPacket subpacket = changeProperty.BuildPacket(player.actorId);
|
||||
player.playerSession.QueuePacket(subpacket);
|
||||
subpacket.DebugPrintSubPacket();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value.GetType() == curObj.GetType() || TypeDescriptor.GetConverter(value.GetType()).CanConvertTo(curObj.GetType()))
|
||||
{
|
||||
if (value.GetType() == curObj.GetType())
|
||||
parentObj.GetType().GetField(split[split.Length - 1]).SetValue(parentObj, value);
|
||||
else
|
||||
parentObj.GetType().GetField(split[split.Length-1]).SetValue(parentObj, TypeDescriptor.GetConverter(value.GetType()).ConvertTo(value, curObj.GetType()));
|
||||
|
||||
SetActorPropetyPacket changeProperty = new SetActorPropetyPacket(uiFunc);
|
||||
changeProperty.AddProperty(this, name);
|
||||
changeProperty.AddTarget();
|
||||
SubPacket subpacket = changeProperty.BuildPacket(player.actorId);
|
||||
player.playerSession.QueuePacket(subpacket);
|
||||
subpacket.DebugPrintSubPacket();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<float> GetPos()
|
||||
{
|
||||
List<float> pos = new List<float>();
|
||||
|
@ -376,7 +509,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
rotation = rot;
|
||||
|
||||
// todo: handle zone?
|
||||
zone.BroadcastPacketAroundActor(this, MoveActorToPositionPacket.BuildPacket(this.actorId, this.actorId, x, y, z, rot, moveState));
|
||||
zone.BroadcastPacketAroundActor(this, MoveActorToPositionPacket.BuildPacket(actorId, x, y, z, rot, moveState));
|
||||
}
|
||||
|
||||
public Area GetZone()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
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;
|
||||
|
@ -14,6 +13,8 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FFXIVClassic_Map_Server.packets.send;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
|
@ -28,17 +29,23 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
protected string classPath;
|
||||
|
||||
public int boundingGridSize = 50;
|
||||
public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000;
|
||||
public int minX = -5000, minY = -5000, maxX = 5000, maxY = 5000;
|
||||
protected int numXBlocks, numYBlocks;
|
||||
protected int halfWidth, halfHeight;
|
||||
|
||||
private Dictionary<uint, Director> currentDirectors = new Dictionary<uint, Director>();
|
||||
private Object directorLock = new Object();
|
||||
private uint directorIdCount = 0;
|
||||
|
||||
protected Director mWeatherDirector;
|
||||
|
||||
protected List<SpawnLocation> mSpawnLocations = new List<SpawnLocation>();
|
||||
protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>();
|
||||
protected List<Actor>[,] mActorBlock;
|
||||
|
||||
LuaScript areaScript;
|
||||
|
||||
public Area(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
public Area(uint id, string zoneName, ushort regionId, string classPath, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
: base(id)
|
||||
{
|
||||
|
||||
|
@ -56,9 +63,10 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
this.displayNameId = 0;
|
||||
this.customDisplayName = "_areaMaster";
|
||||
this.actorName = String.Format("_areaMaster@{0:X5}",id<<8);
|
||||
this.actorName = String.Format("_areaMaster@{0:X5}", id << 8);
|
||||
|
||||
this.className = className;
|
||||
this.classPath = classPath;
|
||||
this.className = classPath.Substring(classPath.LastIndexOf("/") + 1);
|
||||
|
||||
numXBlocks = (maxX - minX) / boundingGridSize;
|
||||
numYBlocks = (maxY - minY) / boundingGridSize;
|
||||
|
@ -68,40 +76,42 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
for (int y = 0; y < numYBlocks; y++)
|
||||
{
|
||||
for (int x = 0; x < numXBlocks; x++ )
|
||||
for (int x = 0; x < numXBlocks; x++)
|
||||
{
|
||||
mActorBlock[x, y] = new List<Actor>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, "ZoneDefault", lParams);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, "ZoneDefault", lParams);
|
||||
}
|
||||
|
||||
public override BasePacket GetSpawnPackets(uint playerActorId)
|
||||
public override List<SubPacket> GetSpawnPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
subpackets.Add(CreateAddActorPacket(0));
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket());
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
#region Actor Management
|
||||
|
||||
public void AddActorToZone(Actor actor)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (!mActorList.ContainsKey(actor.actorId))
|
||||
mActorList.Add(actor.actorId, actor);
|
||||
}
|
||||
|
||||
int gridX = (int)actor.positionX / boundingGridSize;
|
||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||
|
@ -125,6 +135,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
public void RemoveActorFromZone(Actor actor)
|
||||
{
|
||||
lock (mActorList)
|
||||
mActorList.Remove(actor.actorId);
|
||||
|
||||
int gridX = (int)actor.positionX / boundingGridSize;
|
||||
|
@ -214,6 +225,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
List<Actor> result = new List<Actor>();
|
||||
|
||||
lock (mActorBlock)
|
||||
{
|
||||
for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++)
|
||||
{
|
||||
for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++)
|
||||
|
@ -221,6 +234,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
result.AddRange(mActorBlock[gx, gy]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Remove players if isolation zone
|
||||
if (isIsolated)
|
||||
|
@ -257,6 +271,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
List<Actor> result = new List<Actor>();
|
||||
|
||||
lock (mActorBlock)
|
||||
{
|
||||
for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++)
|
||||
{
|
||||
for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++)
|
||||
|
@ -264,6 +280,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
result.AddRange(mActorBlock[gx, gy]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Remove players if isolation zone
|
||||
if (isIsolated)
|
||||
|
@ -280,14 +297,35 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
#endregion
|
||||
|
||||
public Actor FindActorInZone(uint id)
|
||||
public Actor FindActorInArea(uint id)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (!mActorList.ContainsKey(id))
|
||||
return null;
|
||||
return mActorList[id];
|
||||
}
|
||||
}
|
||||
|
||||
public Actor FindActorInZoneByUniqueID(string uniqueId)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (Actor a in mActorList.Values)
|
||||
{
|
||||
if (a is Npc)
|
||||
{
|
||||
if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId))
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Player FindPCInZone(string name)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (Actor a in mActorList.Values)
|
||||
{
|
||||
|
@ -299,18 +337,26 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Player FindPCInZone(uint id)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
if (!mActorList.ContainsKey(id))
|
||||
return null;
|
||||
return (Player)mActorList[id];
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
//Clear All
|
||||
mActorList.Clear();
|
||||
lock (mActorBlock)
|
||||
{
|
||||
for (int y = 0; y < numYBlocks; y++)
|
||||
{
|
||||
for (int x = 0; x < numXBlocks; x++)
|
||||
|
@ -319,6 +365,14 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BroadcastPacketsAroundActor(Actor actor, List<SubPacket> packets)
|
||||
{
|
||||
foreach (SubPacket packet in packets)
|
||||
BroadcastPacketAroundActor(actor, packet);
|
||||
}
|
||||
|
||||
public void BroadcastPacketAroundActor(Actor actor, SubPacket packet)
|
||||
{
|
||||
|
@ -333,7 +387,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
if (isIsolated && packet.header.sourceId != a.actorId)
|
||||
continue;
|
||||
|
||||
SubPacket clonedPacket = new SubPacket(packet, actor.actorId);
|
||||
SubPacket clonedPacket = new SubPacket(packet, a.actorId);
|
||||
Player p = (Player)a;
|
||||
p.QueuePacket(clonedPacket);
|
||||
}
|
||||
|
@ -347,31 +401,192 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
if (actorClass == null)
|
||||
return;
|
||||
|
||||
Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, actorId, location.x, location.y, location.z, location.rot, location.state, location.animId, null);
|
||||
uint zoneId;
|
||||
|
||||
if (this is PrivateArea)
|
||||
zoneId = ((PrivateArea)this).GetParentZone().actorId;
|
||||
else
|
||||
zoneId = actorId;
|
||||
|
||||
Npc npc = new Npc(mActorList.Count + 1, actorClass, location.uniqueId, this, location.x, location.y, location.z, location.rot, location.state, location.animId, null);
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
|
||||
AddActorToZone(npc);
|
||||
}
|
||||
|
||||
public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, float rot = 0, ushort state = 0, uint animId = 0)
|
||||
{
|
||||
ActorClass actorClass = Server.GetWorldManager().GetActorClass(classId);
|
||||
|
||||
if (actorClass == null)
|
||||
return null;
|
||||
|
||||
uint zoneId;
|
||||
|
||||
if (this is PrivateArea)
|
||||
zoneId = ((PrivateArea)this).GetParentZone().actorId;
|
||||
else
|
||||
zoneId = actorId;
|
||||
|
||||
Npc npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null);
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
|
||||
AddActorToZone(npc);
|
||||
|
||||
return npc;
|
||||
}
|
||||
|
||||
public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, uint regionId, uint layoutId)
|
||||
{
|
||||
ActorClass actorClass = Server.GetWorldManager().GetActorClass(classId);
|
||||
|
||||
if (actorClass == null)
|
||||
return null;
|
||||
|
||||
uint zoneId;
|
||||
|
||||
if (this is PrivateArea)
|
||||
zoneId = ((PrivateArea)this).GetParentZone().actorId;
|
||||
else
|
||||
zoneId = actorId;
|
||||
|
||||
Npc npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, 0, regionId, layoutId);
|
||||
|
||||
npc.LoadEventConditions(actorClass.eventConditions);
|
||||
|
||||
AddActorToZone(npc);
|
||||
|
||||
return npc;
|
||||
}
|
||||
|
||||
public void DespawnActor(string uniqueId)
|
||||
{
|
||||
RemoveActorFromZone(FindActorInZoneByUniqueID(uniqueId));
|
||||
}
|
||||
|
||||
public void DespawnActor(Actor actor)
|
||||
{
|
||||
RemoveActorFromZone(actor);
|
||||
}
|
||||
|
||||
public Director GetWeatherDirector()
|
||||
{
|
||||
return mWeatherDirector;
|
||||
}
|
||||
|
||||
public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false)
|
||||
{
|
||||
weatherNormal = weather;
|
||||
|
||||
if (player != null && !zoneWide)
|
||||
{
|
||||
player.QueuePacket(BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime), true, false));
|
||||
player.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime));
|
||||
}
|
||||
if (zoneWide)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (var actor in mActorList)
|
||||
{
|
||||
if (actor.Value is Player)
|
||||
{
|
||||
player = ((Player)actor.Value);
|
||||
player.QueuePacket(BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime), true, false));
|
||||
player.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Director CreateDirector(string path, bool hasContentGroup, params object[] args)
|
||||
{
|
||||
lock (directorLock)
|
||||
{
|
||||
Director director = new Director(directorIdCount, this, path, hasContentGroup, args);
|
||||
currentDirectors.Add(director.actorId, director);
|
||||
directorIdCount++;
|
||||
return director;
|
||||
}
|
||||
}
|
||||
|
||||
public Director CreateGuildleveDirector(uint glid, byte difficulty, Player owner, params object[] args)
|
||||
{
|
||||
String directorScriptPath = "";
|
||||
|
||||
uint type = Server.GetGuildleveGamedata(glid).plateId;
|
||||
|
||||
if (glid == 10801 || glid == 12401 || glid == 11601)
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleTutorial";
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 20021:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleSweepNormal";
|
||||
break;
|
||||
case 20022:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleChaseNormal";
|
||||
break;
|
||||
case 20023:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleOrbNormal";
|
||||
break;
|
||||
case 20024:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleHuntNormal";
|
||||
break;
|
||||
case 20025:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleGatherNormal";
|
||||
break;
|
||||
case 20026:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleRoundNormal";
|
||||
break;
|
||||
case 20027:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleSurviveNormal";
|
||||
break;
|
||||
case 20028:
|
||||
directorScriptPath = "Guildleve/PrivateGLBattleDetectNormal";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lock (directorLock)
|
||||
{
|
||||
GuildleveDirector director = new GuildleveDirector(directorIdCount, this, directorScriptPath, glid, difficulty, owner, args);
|
||||
currentDirectors.Add(director.actorId, director);
|
||||
directorIdCount++;
|
||||
return director;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteDirector(uint id)
|
||||
{
|
||||
lock (directorLock)
|
||||
{
|
||||
if (currentDirectors.ContainsKey(id))
|
||||
{
|
||||
if (!currentDirectors[id].IsDeleted())
|
||||
currentDirectors[id].EndDirector();
|
||||
currentDirectors.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Director GetDirectorById(uint id)
|
||||
{
|
||||
if (currentDirectors.ContainsKey(id))
|
||||
return currentDirectors[id];
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
lock (mActorList)
|
||||
{
|
||||
foreach (Actor a in mActorList.Values)
|
||||
a.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -14,14 +15,15 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
{
|
||||
private Zone parentZone;
|
||||
private string privateAreaName;
|
||||
private uint privateAreaLevel;
|
||||
private uint privateAreaType;
|
||||
|
||||
public PrivateArea(Zone parent, uint id, string className, string privateAreaName, uint privateAreaLevel, ushort bgmDay, ushort bgmNight, ushort bgmBattle)
|
||||
: base(id, parent.zoneName, parent.regionId, className, bgmDay, bgmNight, bgmBattle, parent.isIsolated, parent.isInn, parent.canRideChocobo, parent.canStealth, true)
|
||||
public PrivateArea(Zone parent, uint id, string classPath, string privateAreaName, uint privateAreaType, ushort bgmDay, ushort bgmNight, ushort bgmBattle)
|
||||
: base(id, parent.zoneName, parent.regionId, classPath, bgmDay, bgmNight, bgmBattle, parent.isIsolated, parent.isInn, parent.canRideChocobo, parent.canStealth, true)
|
||||
{
|
||||
this.parentZone = parent;
|
||||
this.zoneName = parent.zoneName;
|
||||
this.privateAreaName = privateAreaName;
|
||||
this.privateAreaLevel = privateAreaLevel;
|
||||
this.privateAreaType = privateAreaType;
|
||||
}
|
||||
|
||||
public string GetPrivateAreaName()
|
||||
|
@ -29,9 +31,9 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
return privateAreaName;
|
||||
}
|
||||
|
||||
public uint GetPrivateAreaLevel()
|
||||
public uint GetPrivateAreaType()
|
||||
{
|
||||
return privateAreaLevel;
|
||||
return privateAreaType;
|
||||
}
|
||||
|
||||
public Zone GetParentZone()
|
||||
|
@ -39,18 +41,17 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
return parentZone;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
|
||||
string path = className;
|
||||
|
||||
if (className.ToLower().Contains("content"))
|
||||
path = "Content/" + className;
|
||||
string realClassName = className.Substring(className.LastIndexOf("/") + 1);
|
||||
|
||||
lParams = LuaUtils.CreateLuaParamList("/Area/PrivateArea/" + path, false, true, zoneName, privateAreaName, 0x9E, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, false, false, false);
|
||||
ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, privateAreaName, privateAreaType, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, false, false, false);
|
||||
ActorInstantiatePacket.BuildPacket(actorId, actorName, realClassName, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, realClassName, lParams);
|
||||
}
|
||||
|
||||
|
||||
|
|
57
FFXIVClassic Map Server/actors/area/PrivateAreaContent.cs
Normal file
57
FFXIVClassic Map Server/actors/area/PrivateAreaContent.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using FFXIVClassic_Map_Server.actors.director;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
{
|
||||
|
||||
class PrivateAreaContent : PrivateArea
|
||||
{
|
||||
private Director currentDirector;
|
||||
private bool isContentFinished = false;
|
||||
|
||||
public static PrivateAreaContent CreateContentArea(String scriptPath)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public PrivateAreaContent(Zone parent, string classPath, string privateAreaName, uint privateAreaType, Director director, Player contentStarter) //TODO: Make it a list
|
||||
: base(parent, parent.actorId, classPath, privateAreaName, privateAreaType, 0, 0, 0)
|
||||
{
|
||||
currentDirector = director;
|
||||
LuaEngine.GetInstance().CallLuaFunction(contentStarter, this, "onCreate", false, currentDirector);
|
||||
}
|
||||
|
||||
public Director GetContentDirector()
|
||||
{
|
||||
return currentDirector;
|
||||
}
|
||||
|
||||
public void ContentFinished()
|
||||
{
|
||||
isContentFinished = true;
|
||||
}
|
||||
|
||||
public void CheckDestroy()
|
||||
{
|
||||
if (isContentFinished)
|
||||
{
|
||||
bool noPlayersLeft = true;
|
||||
foreach (Actor a in mActorList.Values)
|
||||
{
|
||||
if (a is Player)
|
||||
noPlayersLeft = false;
|
||||
}
|
||||
if (noPlayersLeft)
|
||||
GetParentZone().DeleteContentArea(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
@ -10,15 +10,18 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.area
|
||||
{
|
||||
class Zone : Area
|
||||
{
|
||||
Dictionary<string, Dictionary<uint, PrivateArea>> privateAreas = new Dictionary<string, Dictionary<uint, PrivateArea>>();
|
||||
Dictionary<string, List<PrivateAreaContent>> contentAreas = new Dictionary<string, List<PrivateAreaContent>>();
|
||||
Object contentAreasLock = new Object();
|
||||
|
||||
public Zone(uint id, string zoneName, ushort regionId, string className, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
: base(id, zoneName, regionId, className, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, isInstanceRaid)
|
||||
public Zone(uint id, string zoneName, ushort regionId, string classPath, ushort bgmDay, ushort bgmNight, ushort bgmBattle, bool isIsolated, bool isInn, bool canRideChocobo, bool canStealth, bool isInstanceRaid)
|
||||
: base(id, zoneName, regionId, classPath, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, isInstanceRaid)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -26,11 +29,11 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
public void AddPrivateArea(PrivateArea pa)
|
||||
{
|
||||
if (privateAreas.ContainsKey(pa.GetPrivateAreaName()))
|
||||
privateAreas[pa.GetPrivateAreaName()][0] = pa;
|
||||
privateAreas[pa.GetPrivateAreaName()][pa.GetPrivateAreaType()] = pa;
|
||||
else
|
||||
{
|
||||
privateAreas[pa.GetPrivateAreaName()] = new Dictionary<uint, PrivateArea>();
|
||||
privateAreas[pa.GetPrivateAreaName()][0] = pa;
|
||||
privateAreas[pa.GetPrivateAreaName()][pa.GetPrivateAreaType()] = pa;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,13 +51,13 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
return null;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
bool isEntranceDesion = false;
|
||||
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/Area/Zone/" + className, false, true, zoneName, "", -1, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, true, isInstanceRaid, isEntranceDesion);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "", -1, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, true, isInstanceRaid, isEntranceDesion);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
|
||||
}
|
||||
|
||||
public void AddSpawnLocation(SpawnLocation spawn)
|
||||
|
@ -92,5 +95,49 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||
}
|
||||
}
|
||||
|
||||
public Actor FindActorInZone(uint id)
|
||||
{
|
||||
if (!mActorList.ContainsKey(id))
|
||||
{
|
||||
foreach(Dictionary<uint, PrivateArea> paList in privateAreas.Values)
|
||||
{
|
||||
foreach(PrivateArea pa in paList.Values)
|
||||
{
|
||||
Actor actor = pa.FindActorInArea(id);
|
||||
if (actor != null)
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return mActorList[id];
|
||||
}
|
||||
|
||||
public PrivateAreaContent CreateContentArea(Player starterPlayer, string areaClassPath, string contentScript, string areaName, string directorName, params object[] args)
|
||||
{
|
||||
lock (contentAreasLock)
|
||||
{
|
||||
Director director = CreateDirector(directorName, true, args);
|
||||
|
||||
if (director == null)
|
||||
return null;
|
||||
|
||||
if (!contentAreas.ContainsKey(areaName))
|
||||
contentAreas.Add(areaName, new List<PrivateAreaContent>());
|
||||
PrivateAreaContent contentArea = new PrivateAreaContent(this, classPath, areaName, 1, director, starterPlayer);
|
||||
contentAreas[areaName].Add(contentArea);
|
||||
return contentArea;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteContentArea(PrivateAreaContent area)
|
||||
{
|
||||
if (contentAreas.ContainsKey(area.GetPrivateAreaName()))
|
||||
{
|
||||
contentAreas[area.GetPrivateAreaName()].Remove(area);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
|
||||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.Actors.Chara;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using FFXIVClassic_Map_Server.utils;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
|
@ -35,6 +38,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];
|
||||
|
||||
|
@ -48,6 +53,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
public Work work = new Work();
|
||||
public CharaWork charaWork = new CharaWork();
|
||||
|
||||
public Group currentParty = null;
|
||||
public ContentGroup currentContentGroup = null;
|
||||
|
||||
public Character(uint actorID) : base(actorID)
|
||||
{
|
||||
//Init timer array to "notimer"
|
||||
|
@ -55,30 +63,56 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
charaWork.statusShownTime[i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
public SubPacket CreateAppearancePacket(uint playerActorId)
|
||||
public SubPacket CreateAppearancePacket()
|
||||
{
|
||||
SetActorAppearancePacket setappearance = new SetActorAppearancePacket(modelId, appearanceIds);
|
||||
return setappearance.BuildPacket(actorId, playerActorId);
|
||||
return setappearance.BuildPacket(actorId);
|
||||
}
|
||||
|
||||
public SubPacket CreateInitStatusPacket(uint playerActorId)
|
||||
public SubPacket CreateInitStatusPacket()
|
||||
{
|
||||
return (SetActorStatusAllPacket.BuildPacket(actorId, playerActorId, charaWork.status));
|
||||
return (SetActorStatusAllPacket.BuildPacket(actorId, charaWork.status));
|
||||
}
|
||||
|
||||
public SubPacket CreateSetActorIconPacket(uint playerActorId)
|
||||
public SubPacket CreateSetActorIconPacket()
|
||||
{
|
||||
return SetActorIconPacket.BuildPacket(actorId, playerActorId, currentActorIcon);
|
||||
return SetActorIconPacket.BuildPacket(actorId, currentActorIcon);
|
||||
}
|
||||
|
||||
public SubPacket CreateIdleAnimationPacket(uint playerActorId)
|
||||
public SubPacket CreateIdleAnimationPacket()
|
||||
{
|
||||
return SetActorIdleAnimationPacket.BuildPacket(actorId, playerActorId, animationId);
|
||||
return SetActorSubStatPacket.BuildPacket(actorId, 0, 0, 0, 0, 0, 0, animationId);
|
||||
}
|
||||
|
||||
public void SetQuestGraphic(Player player, int graphicNum)
|
||||
{
|
||||
player.QueuePacket(SetActorQuestGraphicPacket.BuildPacket(player.actorId, actorId, graphicNum));
|
||||
player.QueuePacket(SetActorQuestGraphicPacket.BuildPacket(actorId, graphicNum));
|
||||
}
|
||||
|
||||
public void SetCurrentContentGroup(ContentGroup group)
|
||||
{
|
||||
if (group != null)
|
||||
charaWork.currentContentGroup = group.GetTypeId();
|
||||
else
|
||||
charaWork.currentContentGroup = 0;
|
||||
|
||||
currentContentGroup = group;
|
||||
|
||||
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/currentContentGroup", this);
|
||||
propPacketUtil.AddProperty("charaWork.currentContentGroup");
|
||||
zone.BroadcastPacketsAroundActor(this, propPacketUtil.Done());
|
||||
|
||||
}
|
||||
|
||||
public void PlayAnimation(uint animId, bool onlySelf = false)
|
||||
{
|
||||
if (onlySelf)
|
||||
{
|
||||
if (this is Player)
|
||||
((Player)this).QueuePacket(PlayAnimationOnActorPacket.BuildPacket(actorId, animId));
|
||||
}
|
||||
else
|
||||
zone.BroadcastPacketAroundActor(this, PlayAnimationOnActorPacket.BuildPacket(actorId, animId));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
|
||||
public bool betacheck = false;
|
||||
|
||||
public bool[] event_achieve_aetheryte = new bool[512];
|
||||
public bool[] event_achieve_aetheryte = new bool[128];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,21 @@ namespace FFXIVClassic_Map_Server.actors.chara.npc
|
|||
public readonly uint propertyFlags;
|
||||
public readonly string eventConditions;
|
||||
|
||||
public ActorClass(uint id, string classPath, uint nameId, uint propertyFlags, string eventConditions)
|
||||
public readonly ushort pushCommand;
|
||||
public readonly ushort pushCommandSub;
|
||||
public readonly byte pushCommandPriority;
|
||||
|
||||
public ActorClass(uint id, string classPath, uint nameId, uint propertyFlags, string eventConditions, ushort pushCommand, ushort pushCommandSub, byte pushCommandPriority)
|
||||
{
|
||||
this.actorClassId = id;
|
||||
this.classPath = classPath;
|
||||
this.displayNameId = nameId;
|
||||
this.propertyFlags = propertyFlags;
|
||||
this.eventConditions = eventConditions;
|
||||
|
||||
this.pushCommand = pushCommand;
|
||||
this.pushCommandSub = pushCommandSub;
|
||||
this.pushCommandPriority = pushCommandPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors;
|
||||
using FFXIVClassic_Map_Server.actors.area;
|
||||
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;
|
||||
|
@ -25,15 +25,19 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
private uint actorClassId;
|
||||
private string uniqueIdentifier;
|
||||
|
||||
private bool isMapObj = false;
|
||||
private uint layout, instance;
|
||||
|
||||
public NpcWork npcWork = new NpcWork();
|
||||
|
||||
public Npc(int actorNumber, ActorClass actorClass, string uniqueId, uint zoneId, float posX, float posY, float posZ, float rot, ushort actorState, uint animationId, string customDisplayName)
|
||||
: base((4 << 28 | zoneId << 19 | (uint)actorNumber))
|
||||
public Npc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot, ushort actorState, uint animationId, string customDisplayName)
|
||||
: base((4 << 28 | spawnedArea.actorId << 19 | (uint)actorNumber))
|
||||
{
|
||||
this.positionX = posX;
|
||||
this.positionY = posY;
|
||||
this.positionZ = posZ;
|
||||
this.rotation = rot;
|
||||
this.currentMainState = actorState;
|
||||
this.animationId = animationId;
|
||||
|
||||
this.displayNameId = actorClass.displayNameId;
|
||||
|
@ -41,8 +45,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
this.uniqueIdentifier = uniqueId;
|
||||
|
||||
this.zoneId = zoneId;
|
||||
this.zone = Server.GetWorldManager().GetZone(zoneId);
|
||||
this.zoneId = spawnedArea.actorId;
|
||||
this.zone = spawnedArea;
|
||||
|
||||
this.actorClassId = actorClass.actorClassId;
|
||||
|
||||
|
@ -63,38 +67,93 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
for (int i = 0; i < 32; i++ )
|
||||
charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1);
|
||||
|
||||
if (className.Equals("JellyfishScenarioLimsaLv00"))
|
||||
{
|
||||
charaWork.property[2] = 1;
|
||||
npcWork.hateType = 1;
|
||||
}
|
||||
npcWork.pushCommand = actorClass.pushCommand;
|
||||
npcWork.pushCommandSub = actorClass.pushCommandSub;
|
||||
npcWork.pushCommandPriority = actorClass.pushCommandPriority;
|
||||
|
||||
npcWork.pushCommand = 0x271D;
|
||||
npcWork.pushCommandPriority = 1;
|
||||
if (actorClassId == 1080078 || actorClassId == 1080079 || actorClassId == 1080080 || (actorClassId >= 1080123 && actorClassId <= 1080135) || (actorClassId >= 5000001 && actorClassId <= 5000090) || (actorClassId >= 5900001 && actorClassId <= 5900038))
|
||||
{
|
||||
isMapObj = true;
|
||||
List<LuaParam> lParams = LuaEngine.GetInstance().CallLuaFunctionForReturn(null, this, "init", false);
|
||||
if (lParams == null || lParams.Count < 6)
|
||||
isMapObj = false;
|
||||
else
|
||||
{
|
||||
layout = (uint)(Int32)lParams[4].value;
|
||||
instance = (uint)(Int32)lParams[5].value;
|
||||
isStatic = true;
|
||||
}
|
||||
}
|
||||
|
||||
GenerateActorName((int)actorNumber);
|
||||
}
|
||||
|
||||
public SubPacket CreateAddActorPacket(uint playerActorId)
|
||||
public Npc(int actorNumber, ActorClass actorClass, string uniqueId, Area spawnedArea, float posX, float posY, float posZ, float rot, uint layout, uint instance)
|
||||
: base((4 << 28 | spawnedArea.actorId << 19 | (uint)actorNumber))
|
||||
{
|
||||
return AddActorPacket.BuildPacket(actorId, playerActorId, 8);
|
||||
this.positionX = posX;
|
||||
this.positionY = posY;
|
||||
this.positionZ = posZ;
|
||||
this.rotation = rot;
|
||||
this.currentMainState = 0;
|
||||
this.animationId = 0;
|
||||
|
||||
this.displayNameId = actorClass.displayNameId;
|
||||
|
||||
this.uniqueIdentifier = uniqueId;
|
||||
|
||||
this.zoneId = spawnedArea.actorId;
|
||||
this.zone = spawnedArea;
|
||||
|
||||
this.actorClassId = actorClass.actorClassId;
|
||||
|
||||
LoadNpcAppearance(actorClass.actorClassId);
|
||||
|
||||
this.classPath = actorClass.classPath;
|
||||
className = classPath.Substring(classPath.LastIndexOf("/") + 1);
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1);
|
||||
|
||||
npcWork.pushCommand = actorClass.pushCommand;
|
||||
npcWork.pushCommandSub = actorClass.pushCommandSub;
|
||||
npcWork.pushCommandPriority = actorClass.pushCommandPriority;
|
||||
|
||||
this.isMapObj = true;
|
||||
this.layout = layout;
|
||||
this.instance = instance;
|
||||
|
||||
GenerateActorName((int)actorNumber);
|
||||
}
|
||||
|
||||
public SubPacket CreateAddActorPacket()
|
||||
{
|
||||
return AddActorPacket.BuildPacket(actorId, 8);
|
||||
}
|
||||
|
||||
// actorClassId, [], [], numBattleCommon, [battleCommon], numEventCommon, [eventCommon], args for either initForBattle/initForEvent
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public override SubPacket CreateScriptBindPacket(Player player)
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
|
||||
Player player = Server.GetWorldManager().GetPCInWorld(playerActorId);
|
||||
lParams = DoActorInit(player);
|
||||
lParams = LuaEngine.GetInstance().CallLuaFunctionForReturn(player, this, "init", false);
|
||||
|
||||
if (lParams != null && lParams.Count >= 3 && lParams[2].typeID == 0 && (int)lParams[2].value == 0)
|
||||
isStatic = true;
|
||||
else
|
||||
{
|
||||
// charaWork.property[2] = 1;
|
||||
// npcWork.hateType = 1;
|
||||
}
|
||||
|
||||
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);
|
||||
//ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams);
|
||||
isStatic = true;
|
||||
//ActorInstantiatePacket.BuildPacket(actorId, actorName, classNameFake, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, classNameFake, lParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -107,32 +166,40 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
lParams.Insert(6, new LuaParam(0, (int)actorClassId));
|
||||
}
|
||||
|
||||
//ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
//ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams).DebugPrintSubPacket();
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
|
||||
}
|
||||
|
||||
public override BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
|
||||
public override List<SubPacket> GetSpawnPackets(Player player, ushort spawnType)
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId));
|
||||
subpackets.AddRange(GetEventConditionPackets(playerActorId));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x0));
|
||||
subpackets.Add(CreateAppearancePacket(playerActorId));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIdleAnimationPacket(playerActorId));
|
||||
subpackets.Add(CreateInitStatusPacket(playerActorId));
|
||||
subpackets.Add(CreateSetActorIconPacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
subpackets.Add(CreateAddActorPacket());
|
||||
subpackets.AddRange(GetEventConditionPackets());
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0x0));
|
||||
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
if (isMapObj)
|
||||
subpackets.Add(SetActorBGPropertiesPacket.BuildPacket(actorId, instance, layout));
|
||||
else
|
||||
subpackets.Add(CreateAppearancePacket());
|
||||
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIdleAnimationPacket());
|
||||
subpackets.Add(CreateInitStatusPacket());
|
||||
subpackets.Add(CreateSetActorIconPacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket(player));
|
||||
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public override BasePacket GetInitPackets(uint playerActorId)
|
||||
public override List<SubPacket> GetInitPackets()
|
||||
{
|
||||
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this, playerActorId);
|
||||
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this);
|
||||
|
||||
//Potential
|
||||
propPacketUtil.AddProperty("charaWork.battleSave.potencial");
|
||||
|
||||
//Properties
|
||||
for (int i = 0; i < charaWork.property.Length; i++)
|
||||
|
@ -174,10 +241,16 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
}
|
||||
|
||||
propPacketUtil.AddProperty("npcWork.hateType");
|
||||
propPacketUtil.AddProperty("npcWork.pushCommand");
|
||||
propPacketUtil.AddProperty("npcWork.pushCommandPriority");
|
||||
|
||||
return BasePacket.CreatePacket(propPacketUtil.Done(), true, false);
|
||||
if (npcWork.pushCommand != 0)
|
||||
{
|
||||
propPacketUtil.AddProperty("npcWork.pushCommand");
|
||||
if (npcWork.pushCommandSub != 0)
|
||||
propPacketUtil.AddProperty("npcWork.pushCommandSub");
|
||||
propPacketUtil.AddProperty("npcWork.pushCommandPriority");
|
||||
}
|
||||
|
||||
return propPacketUtil.Done();
|
||||
}
|
||||
|
||||
public string GetUniqueId()
|
||||
|
@ -190,6 +263,12 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
return actorClassId;
|
||||
}
|
||||
|
||||
public void ChangeNpcAppearance(uint id)
|
||||
{
|
||||
LoadNpcAppearance(id);
|
||||
zone.BroadcastPacketAroundActor(this, CreateAppearancePacket());
|
||||
}
|
||||
|
||||
public void LoadNpcAppearance(uint id)
|
||||
{
|
||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||
|
@ -298,118 +377,33 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
this.eventConditions = conditions;
|
||||
}
|
||||
|
||||
public List<LuaParam> DoActorInit(Player player)
|
||||
public void DoOnActorSpawn(Player player)
|
||||
{
|
||||
LuaScript parent = null, child = null;
|
||||
|
||||
if (File.Exists("./scripts/base/" + classPath + ".lua"))
|
||||
parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua");
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier));
|
||||
|
||||
if (parent == null && child == null)
|
||||
{
|
||||
LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName()));
|
||||
return null;
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, this, "onSpawn", true);
|
||||
}
|
||||
|
||||
DynValue result;
|
||||
|
||||
if (child != null && child.Globals["init"] != null)
|
||||
result = child.Call(child.Globals["init"], this);
|
||||
else if (parent != null && parent.Globals["init"] != null)
|
||||
result = parent.Call(parent.Globals["init"], this);
|
||||
else
|
||||
return null;
|
||||
|
||||
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||
return lparams;
|
||||
}
|
||||
|
||||
public Coroutine GetEventStartCoroutine(Player player)
|
||||
public void PlayMapObjAnimation(Player player, string animationName)
|
||||
{
|
||||
LuaScript parent = null, child = null;
|
||||
player.QueuePacket(PlayBGAnimation.BuildPacket(actorId, animationName));
|
||||
}
|
||||
|
||||
if (File.Exists("./scripts/base/" + classPath + ".lua"))
|
||||
parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua");
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier));
|
||||
|
||||
if (parent == null && child == null)
|
||||
public void Despawn()
|
||||
{
|
||||
LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName()));
|
||||
return null;
|
||||
zone.DespawnActor(this);
|
||||
}
|
||||
|
||||
//Run Script
|
||||
Coroutine coroutine;
|
||||
|
||||
if (child != null && !child.Globals.Get("onEventStarted").IsNil())
|
||||
coroutine = child.CreateCoroutine(child.Globals["onEventStarted"]).Coroutine;
|
||||
else if (parent.Globals.Get("onEventStarted") != null && !parent.Globals.Get("onEventStarted").IsNil())
|
||||
coroutine = parent.CreateCoroutine(parent.Globals["onEventStarted"]).Coroutine;
|
||||
else
|
||||
return null;
|
||||
|
||||
return coroutine;
|
||||
}
|
||||
|
||||
public void DoEventUpdate(Player player, EventUpdatePacket eventUpdate)
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
LuaScript parent = null, child = null;
|
||||
LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime);
|
||||
}
|
||||
|
||||
if (File.Exists("./scripts/base/" + classPath + ".lua"))
|
||||
parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua");
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier));
|
||||
|
||||
if (parent == null && child == null)
|
||||
//A party member list packet came, set the party
|
||||
/* public void SetParty(MonsterPartyGroup group)
|
||||
{
|
||||
//LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName()));
|
||||
return;
|
||||
if (group is MonsterPartyGroup)
|
||||
currentParty = group;
|
||||
}
|
||||
*/
|
||||
|
||||
//Have to do this to combine LuaParams
|
||||
List<Object> objects = new List<Object>();
|
||||
objects.Add(player);
|
||||
objects.Add(this);
|
||||
objects.Add(eventUpdate.val2);
|
||||
objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams));
|
||||
|
||||
//Run Script
|
||||
DynValue result;
|
||||
|
||||
if (child != null && !child.Globals.Get("onEventUpdate").IsNil())
|
||||
result = child.Call(child.Globals["onEventUpdate"], objects.ToArray());
|
||||
else if (!parent.Globals.Get("onEventUpdate").IsNil())
|
||||
result = parent.Call(parent.Globals["onEventUpdate"], objects.ToArray());
|
||||
else
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
internal void DoOnActorSpawn(Player player)
|
||||
{
|
||||
LuaScript parent = null, child = null;
|
||||
|
||||
if (File.Exists("./scripts/base/" + classPath + ".lua"))
|
||||
parent = LuaEngine.LoadScript("./scripts/base/" + classPath + ".lua");
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier)))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", zone.zoneName, className, uniqueIdentifier));
|
||||
|
||||
if (parent == null && child == null)
|
||||
{
|
||||
//LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName()));
|
||||
return;
|
||||
}
|
||||
|
||||
//Run Script
|
||||
if (child != null && child.Globals["onSpawn"] != null)
|
||||
child.Call(child.Globals["onSpawn"], player, this);
|
||||
else if (parent != null && parent.Globals["onSpawn"] != null)
|
||||
parent.Call(parent.Globals["onSpawn"], player, this);
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
{
|
||||
class NpcWork
|
||||
{
|
||||
public short pushCommand;
|
||||
public ushort pushCommand;
|
||||
public int pushCommandSub;
|
||||
public byte pushCommandPriority;
|
||||
public byte hateType;
|
||||
public byte hateType = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -64,24 +63,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
}
|
||||
}
|
||||
|
||||
toPlayer.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, toPlayer.actorId, 0x23, Inventory.EQUIPMENT_OTHERPLAYER));
|
||||
toPlayer.QueuePacket(InventorySetBeginPacket.BuildPacket(owner.actorId, 0x23, Inventory.EQUIPMENT_OTHERPLAYER));
|
||||
int currentIndex = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (items.Count - currentIndex >= 16)
|
||||
toPlayer.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, toPlayer.actorId, items, ref currentIndex));
|
||||
toPlayer.QueuePacket(InventoryListX16Packet.BuildPacket(owner.actorId, items, ref currentIndex));
|
||||
else if (items.Count - currentIndex > 1)
|
||||
toPlayer.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, toPlayer.actorId, items, ref currentIndex));
|
||||
toPlayer.QueuePacket(InventoryListX08Packet.BuildPacket(owner.actorId, items, ref currentIndex));
|
||||
else if (items.Count - currentIndex == 1)
|
||||
{
|
||||
toPlayer.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, toPlayer.actorId, items[currentIndex]));
|
||||
toPlayer.QueuePacket(InventoryListX01Packet.BuildPacket(owner.actorId, items[currentIndex]));
|
||||
currentIndex++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
toPlayer.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId, toPlayer.actorId));
|
||||
toPlayer.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void SendFullEquipment(bool DoClear)
|
||||
|
|
|
@ -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;
|
||||
|
@ -102,7 +102,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
if (!IsSpaceForAdd(itemId, quantity))
|
||||
return false;
|
||||
|
||||
Item gItem = Server.GetItemGamedata(itemId);
|
||||
ItemData gItem = Server.GetItemGamedata(itemId);
|
||||
List<ushort> slotsToUpdate = new List<ushort>();
|
||||
List<SubPacket> addItemPackets = new List<SubPacket>();
|
||||
|
||||
|
@ -185,7 +185,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
//New item that spilled over
|
||||
for (int i = 0; i < itemId.Length; i++)
|
||||
{
|
||||
Item gItem = Server.GetItemGamedata(itemId[i]);
|
||||
ItemData gItem = Server.GetItemGamedata(itemId[i]);
|
||||
InventoryItem addedItem = Database.AddItem(owner, itemId[i], 1, (byte)1, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode);
|
||||
list.Add(addedItem);
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
|
||||
}
|
||||
|
||||
public void RemoveItem(ulong itemDBId)
|
||||
public void RemoveItemByUniqueId(ulong itemDBId)
|
||||
{
|
||||
ushort slot = 0;
|
||||
InventoryItem toDelete = null;
|
||||
|
@ -314,7 +314,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
|
||||
}
|
||||
|
||||
public void RemoveItem(ushort slot)
|
||||
public void RemoveItemAtSlot(ushort slot)
|
||||
{
|
||||
if (slot >= list.Count)
|
||||
return;
|
||||
|
@ -467,7 +467,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
InventoryItem item = list[i];
|
||||
Item gItem = Server.GetItemGamedata(item.itemId);
|
||||
ItemData gItem = Server.GetItemGamedata(item.itemId);
|
||||
if (item.itemId == itemId && item.quantity < gItem.maxStack)
|
||||
{
|
||||
quantityCount -= (gItem.maxStack - item.quantity);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,8 +18,8 @@
|
|||
|
||||
public bool isContentsCommand;
|
||||
|
||||
public int castCommandClient;
|
||||
public int castEndClient;
|
||||
public uint castCommandClient;
|
||||
public uint castEndClient;
|
||||
|
||||
public int[] comboNextCommandId = new int[2];
|
||||
public float comboCostBonusRate;
|
||||
|
|
|
@ -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;
|
||||
|
@ -18,24 +18,24 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
this.className = "Debug";
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/System/Debug.prog", false, false, false, false, true, 0xC51F, true, true);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
|
||||
}
|
||||
|
||||
public override BasePacket GetSpawnPackets(uint playerActorId)
|
||||
public override List<SubPacket> GetSpawnPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
subpackets.Add(CreateAddActorPacket(0));
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket());
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,50 +1,321 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
|
||||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.area;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using MoonSharp.Interpreter;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director
|
||||
{
|
||||
class Director : Actor
|
||||
{
|
||||
Player owner;
|
||||
private uint directorId;
|
||||
private string directorScriptPath;
|
||||
private List<Actor> members = new List<Actor>();
|
||||
protected ContentGroup contentGroup;
|
||||
private bool isCreated = false;
|
||||
private bool isDeleted = false;
|
||||
private bool isDeleting = false;
|
||||
|
||||
public Director(Player owner, uint id) : base(id)
|
||||
private Script directorScript;
|
||||
private Coroutine currentCoroutine;
|
||||
|
||||
public Director(uint id, Area zone, string directorPath, bool hasContentGroup, params object[] args)
|
||||
: base((6 << 28 | zone.actorId << 19 | (uint)id))
|
||||
{
|
||||
this.owner = owner;
|
||||
directorId = id;
|
||||
this.zone = zone;
|
||||
this.zoneId = zone.actorId;
|
||||
directorScriptPath = directorPath;
|
||||
|
||||
LoadLuaScript();
|
||||
|
||||
if (hasContentGroup)
|
||||
contentGroup = Server.GetWorldManager().CreateContentGroup(this, GetMembers());
|
||||
|
||||
eventConditions = new EventList();
|
||||
eventConditions.noticeEventConditions = new List<EventList.NoticeEventCondition>();
|
||||
eventConditions.noticeEventConditions.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE,0x0));
|
||||
eventConditions.noticeEventConditions.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
|
||||
eventConditions.noticeEventConditions.Add(new EventList.NoticeEventCondition("reqForChild", 0x0, 0x1));
|
||||
}
|
||||
|
||||
public virtual BasePacket GetSpawnPackets(uint playerActorId, uint spawnType)
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> actualLParams = new List<LuaParam>();
|
||||
actualLParams.Insert(0, new LuaParam(2, classPath));
|
||||
actualLParams.Insert(1, new LuaParam(4, 4));
|
||||
actualLParams.Insert(2, new LuaParam(4, 4));
|
||||
actualLParams.Insert(3, new LuaParam(4, 4));
|
||||
actualLParams.Insert(4, new LuaParam(4, 4));
|
||||
actualLParams.Insert(5, new LuaParam(4, 4));
|
||||
|
||||
List<LuaParam> lparams = LuaEngine.GetInstance().CallLuaFunctionForReturn(null, this, "init", false);
|
||||
for (int i = 1; i < lparams.Count; i++)
|
||||
actualLParams.Add(lparams[i]);
|
||||
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, actualLParams);
|
||||
}
|
||||
|
||||
public override List<SubPacket> GetSpawnPackets(ushort spawnType = 1)
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
||||
subpackets.AddRange(GetEventConditionPackets(playerActorId));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
subpackets.Add(CreateAddActorPacket(0));
|
||||
subpackets.AddRange(GetEventConditionPackets());
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket());
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public override BasePacket GetInitPackets(uint playerActorId)
|
||||
public override List<SubPacket> GetInitPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
SetActorPropetyPacket initProperties = new SetActorPropetyPacket("/_init");
|
||||
initProperties.AddTarget();
|
||||
return BasePacket.CreatePacket(initProperties.BuildPacket(playerActorId, actorId), true, false);
|
||||
subpackets.Add(initProperties.BuildPacket(actorId));
|
||||
return subpackets;
|
||||
}
|
||||
|
||||
public void OnTalked(Npc npc)
|
||||
public void OnTalkEvent(Player player, Npc npc)
|
||||
{
|
||||
LuaEngine.DoDirectorOnTalked(this, owner, npc);
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, this, "onTalkEvent", false, npc);
|
||||
}
|
||||
|
||||
public void OnCommand(Command command)
|
||||
public void OnCommandEvent(Player player, Command command)
|
||||
{
|
||||
LuaEngine.DoDirectorOnCommand(this, owner, command);
|
||||
LuaEngine.GetInstance().CallLuaFunction(player, this, "onCommandEvent", false, command);
|
||||
}
|
||||
|
||||
public void StartDirector(bool spawnImmediate, params object[] args)
|
||||
{
|
||||
object[] args2 = new object[args.Length + 1];
|
||||
args2[0] = this;
|
||||
Array.Copy(args, 0, args2, 1, args.Length);
|
||||
|
||||
List<LuaParam> lparams = CallLuaScript("init", args2);
|
||||
|
||||
if (lparams.Count >= 1 && lparams[0].value is string)
|
||||
{
|
||||
classPath = (string)lparams[0].value;
|
||||
className = classPath.Substring(classPath.LastIndexOf("/") + 1);
|
||||
GenerateActorName((int)directorId);
|
||||
isCreated = true;
|
||||
}
|
||||
|
||||
if (isCreated && spawnImmediate)
|
||||
{
|
||||
if (contentGroup != null)
|
||||
contentGroup.Start();
|
||||
|
||||
foreach (Player p in GetPlayerMembers())
|
||||
{
|
||||
p.QueuePackets(GetSpawnPackets());
|
||||
p.QueuePackets(GetInitPackets());
|
||||
}
|
||||
}
|
||||
|
||||
if (this is GuildleveDirector)
|
||||
{
|
||||
((GuildleveDirector)this).LoadGuildleve();
|
||||
}
|
||||
|
||||
StartCoroutine("main", this);
|
||||
}
|
||||
|
||||
public void StartContentGroup()
|
||||
{
|
||||
if (contentGroup != null)
|
||||
contentGroup.Start();
|
||||
}
|
||||
|
||||
public void EndDirector()
|
||||
{
|
||||
isDeleting = true;
|
||||
|
||||
if (contentGroup != null)
|
||||
contentGroup.DeleteGroup();
|
||||
|
||||
if (this is GuildleveDirector)
|
||||
((GuildleveDirector)this).EndGuildleveDirector();
|
||||
|
||||
List<Actor> players = GetPlayerMembers();
|
||||
foreach (Actor player in players)
|
||||
((Player)player).RemoveDirector(this);
|
||||
members.Clear();
|
||||
isDeleted = true;
|
||||
Server.GetWorldManager().GetZone(zoneId).DeleteDirector(actorId);
|
||||
}
|
||||
|
||||
public void AddMember(Actor actor)
|
||||
{
|
||||
if (!members.Contains(actor))
|
||||
{
|
||||
members.Add(actor);
|
||||
|
||||
if (contentGroup != null)
|
||||
contentGroup.AddMember(actor);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveMember(Actor actor)
|
||||
{
|
||||
if (members.Contains(actor))
|
||||
members.Remove(actor);
|
||||
if (contentGroup != null)
|
||||
contentGroup.RemoveMember(actor.actorId);
|
||||
if (GetPlayerMembers().Count == 0 && !isDeleting)
|
||||
EndDirector();
|
||||
}
|
||||
|
||||
public List<Actor> GetMembers()
|
||||
{
|
||||
return members;
|
||||
}
|
||||
|
||||
public List<Actor> GetPlayerMembers()
|
||||
{
|
||||
return members.FindAll(s => s is Player);
|
||||
}
|
||||
|
||||
public List<Actor> GetNpcMembers()
|
||||
{
|
||||
return members.FindAll(s => s is Npc);
|
||||
}
|
||||
|
||||
public bool IsCreated()
|
||||
{
|
||||
return isCreated;
|
||||
}
|
||||
|
||||
public bool IsDeleted()
|
||||
{
|
||||
return isDeleted;
|
||||
}
|
||||
|
||||
public bool HasContentGroup()
|
||||
{
|
||||
return contentGroup != null;
|
||||
}
|
||||
|
||||
public ContentGroup GetContentGroup()
|
||||
{
|
||||
return contentGroup;
|
||||
}
|
||||
|
||||
public void GenerateActorName(int actorNumber)
|
||||
{
|
||||
//Format Class Name
|
||||
string className = this.className;
|
||||
|
||||
className = Char.ToLowerInvariant(className[0]) + className.Substring(1);
|
||||
|
||||
//Format Zone Name
|
||||
string zoneName = zone.zoneName.Replace("Field", "Fld")
|
||||
.Replace("Dungeon", "Dgn")
|
||||
.Replace("Town", "Twn")
|
||||
.Replace("Battle", "Btl")
|
||||
.Replace("Test", "Tes")
|
||||
.Replace("Event", "Evt")
|
||||
.Replace("Ship", "Shp")
|
||||
.Replace("Office", "Ofc");
|
||||
if (zone is PrivateArea)
|
||||
{
|
||||
//Check if "normal"
|
||||
zoneName = zoneName.Remove(zoneName.Length - 1, 1) + "P";
|
||||
}
|
||||
zoneName = Char.ToLowerInvariant(zoneName[0]) + zoneName.Substring(1);
|
||||
|
||||
try
|
||||
{
|
||||
className = className.Substring(0, 20 - zoneName.Length);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException e)
|
||||
{ }
|
||||
|
||||
//Convert actor number to base 63
|
||||
string classNumber = Utils.ToStringBase63(actorNumber);
|
||||
|
||||
//Get stuff after @
|
||||
uint zoneId = zone.actorId;
|
||||
uint privLevel = 0;
|
||||
if (zone is PrivateArea)
|
||||
privLevel = ((PrivateArea)zone).GetPrivateAreaType();
|
||||
|
||||
actorName = String.Format("{0}_{1}_{2}@{3:X3}{4:X2}", className, zoneName, classNumber, zoneId, privLevel);
|
||||
}
|
||||
|
||||
public string GetScriptPath()
|
||||
{
|
||||
return directorScriptPath;
|
||||
}
|
||||
|
||||
private void LoadLuaScript()
|
||||
{
|
||||
string luaPath = String.Format(LuaEngine.FILEPATH_DIRECTORS, GetScriptPath());
|
||||
directorScript = LuaEngine.LoadScript(luaPath);
|
||||
if (directorScript == null)
|
||||
Program.Log.Error("Could not find script for director {0}.", GetName());
|
||||
}
|
||||
|
||||
private List<LuaParam> CallLuaScript(string funcName, params object[] args)
|
||||
{
|
||||
if (directorScript != null)
|
||||
{
|
||||
if (!directorScript.Globals.Get(funcName).IsNil())
|
||||
{
|
||||
DynValue result = directorScript.Call(directorScript.Globals[funcName], args);
|
||||
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||
return lparams;
|
||||
}
|
||||
else
|
||||
Program.Log.Error("Could not find script for director {0}.", GetName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<LuaParam> StartCoroutine(string funcName, params object[] args)
|
||||
{
|
||||
if (directorScript != null)
|
||||
{
|
||||
if (!directorScript.Globals.Get(funcName).IsNil())
|
||||
{
|
||||
currentCoroutine = directorScript.CreateCoroutine(directorScript.Globals[funcName]).Coroutine;
|
||||
DynValue value = currentCoroutine.Resume(args);
|
||||
LuaEngine.GetInstance().ResolveResume(null, currentCoroutine, value);
|
||||
}
|
||||
else
|
||||
Program.Log.Error("Could not find script for director {0}.", GetName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnEventStart(Player player, object[] args)
|
||||
{
|
||||
object[] args2 = new object[args.Length + (player == null ? 1 : 2)];
|
||||
Array.Copy(args, 0, args2, (player == null ? 1 : 2), args.Length);
|
||||
if (player != null)
|
||||
{
|
||||
args2[0] = player;
|
||||
args2[1] = this;
|
||||
}
|
||||
else
|
||||
args2[0] = this;
|
||||
|
||||
Coroutine coroutine = directorScript.CreateCoroutine(directorScript.Globals["onEventStarted"]).Coroutine;
|
||||
DynValue value = coroutine.Resume(args2);
|
||||
LuaEngine.GetInstance().ResolveResume(player, coroutine, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
256
FFXIVClassic Map Server/actors/director/GuildleveDirector.cs
Normal file
256
FFXIVClassic Map Server/actors/director/GuildleveDirector.cs
Normal file
|
@ -0,0 +1,256 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.area;
|
||||
using FFXIVClassic_Map_Server.actors.director.Work;
|
||||
using FFXIVClassic_Map_Server.actors.group;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director
|
||||
{
|
||||
class GuildleveDirector : Director
|
||||
{
|
||||
public uint guildleveId;
|
||||
public Player guildleveOwner;
|
||||
public byte selectedDifficulty;
|
||||
|
||||
public GuildleveData guildleveData;
|
||||
public GuildleveWork guildleveWork = new GuildleveWork();
|
||||
|
||||
public bool isEnded = false;
|
||||
public uint completionTime = 0;
|
||||
|
||||
public GuildleveDirector(uint id, Area zone, string directorPath, uint guildleveId, byte selectedDifficulty, Player guildleveOwner, params object[] args)
|
||||
: base(id, zone, directorPath, true, args)
|
||||
{
|
||||
this.guildleveId = guildleveId;
|
||||
this.selectedDifficulty = selectedDifficulty;
|
||||
this.guildleveData = Server.GetGuildleveGamedata(guildleveId);
|
||||
this.guildleveOwner = guildleveOwner;
|
||||
|
||||
guildleveWork.aimNum[0] = guildleveData.aimNum[0];
|
||||
guildleveWork.aimNum[1] = guildleveData.aimNum[1];
|
||||
guildleveWork.aimNum[2] = guildleveData.aimNum[2];
|
||||
guildleveWork.aimNum[3] = guildleveData.aimNum[3];
|
||||
|
||||
if (guildleveWork.aimNum[0] != 0)
|
||||
guildleveWork.uiState[0] = 1;
|
||||
if (guildleveWork.aimNum[1] != 0)
|
||||
guildleveWork.uiState[1] = 1;
|
||||
if (guildleveWork.aimNum[2] != 0)
|
||||
guildleveWork.uiState[2] = 1;
|
||||
if (guildleveWork.aimNum[3] != 0)
|
||||
guildleveWork.uiState[3] = 1;
|
||||
|
||||
guildleveWork.aimNumNow[0] = guildleveWork.aimNumNow[1] = guildleveWork.aimNumNow[2] = guildleveWork.aimNumNow[3] = 0;
|
||||
}
|
||||
|
||||
public void LoadGuildleve()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void StartGuildleve()
|
||||
{
|
||||
foreach (Actor p in GetPlayerMembers())
|
||||
{
|
||||
Player player = (Player) p;
|
||||
|
||||
//Set music
|
||||
if (guildleveData.location == 1)
|
||||
player.ChangeMusic(22);
|
||||
else if (guildleveData.location == 2)
|
||||
player.ChangeMusic(14);
|
||||
else if (guildleveData.location == 3)
|
||||
player.ChangeMusic(26);
|
||||
else if (guildleveData.location == 4)
|
||||
player.ChangeMusic(16);
|
||||
|
||||
//Show Start Messages
|
||||
player.SendGameMessage(Server.GetWorldManager().GetActor(), 50022, 0x20, guildleveId, selectedDifficulty);
|
||||
player.SendDataPacket("attention", Server.GetWorldManager().GetActor(), "", 50022, guildleveId, selectedDifficulty);
|
||||
player.SendGameMessage(Server.GetWorldManager().GetActor(), 50026, 0x20, (object)(int)guildleveData.timeLimit);
|
||||
}
|
||||
|
||||
guildleveWork.startTime = Utils.UnixTimeStampUTC();
|
||||
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("guildleveWork/start", this);
|
||||
propertyBuilder.AddProperty("guildleveWork.startTime");
|
||||
SendPacketsToPlayers(propertyBuilder.Done());
|
||||
}
|
||||
|
||||
public void EndGuildleve(bool wasCompleted)
|
||||
{
|
||||
if (isEnded)
|
||||
return;
|
||||
isEnded = true;
|
||||
|
||||
completionTime = Utils.UnixTimeStampUTC() - guildleveWork.startTime;
|
||||
|
||||
if (wasCompleted)
|
||||
{
|
||||
foreach (Actor a in GetPlayerMembers())
|
||||
{
|
||||
Player player = (Player)a;
|
||||
player.MarkGuildleve(guildleveId, true, true);
|
||||
player.PlayAnimation(0x02000002, true);
|
||||
player.ChangeMusic(81);
|
||||
player.SendGameMessage(Server.GetWorldManager().GetActor(), 50023, 0x20, (object)(int)guildleveId);
|
||||
player.SendDataPacket("attention", Server.GetWorldManager().GetActor(), "", 50023, (object)(int)guildleveId);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Actor a in GetNpcMembers())
|
||||
{
|
||||
Npc npc = (Npc)a;
|
||||
npc.Despawn();
|
||||
RemoveMember(a);
|
||||
}
|
||||
|
||||
guildleveWork.startTime = 0;
|
||||
guildleveWork.signal = -1;
|
||||
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("guildleveWork/signal", this);
|
||||
propertyBuilder.AddProperty("guildleveWork.signal");
|
||||
propertyBuilder.NewTarget("guildleveWork/start");
|
||||
propertyBuilder.AddProperty("guildleveWork.startTime");
|
||||
SendPacketsToPlayers(propertyBuilder.Done());
|
||||
|
||||
if (wasCompleted)
|
||||
{
|
||||
Npc aetheryteNode = zone.SpawnActor(1200040, String.Format("{0}:warpExit", guildleveOwner.actorName), guildleveOwner.positionX, guildleveOwner.positionY, guildleveOwner.positionZ);
|
||||
AddMember(aetheryteNode);
|
||||
|
||||
foreach (Actor a in GetPlayerMembers())
|
||||
{
|
||||
Player player = (Player)a;
|
||||
player.SendGameMessage(Server.GetWorldManager().GetActor(), 50029, 0x20);
|
||||
player.SendGameMessage(Server.GetWorldManager().GetActor(), 50032, 0x20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AbandonGuildleve()
|
||||
{
|
||||
foreach (Actor p in GetPlayerMembers())
|
||||
{
|
||||
Player player = (Player)p;
|
||||
player.SendGameMessage(Server.GetWorldManager().GetActor(), 50147, 0x20, (object)guildleveId);
|
||||
player.MarkGuildleve(guildleveId, true, false);
|
||||
}
|
||||
|
||||
EndGuildleve(false);
|
||||
EndDirector();
|
||||
}
|
||||
|
||||
//Delete ContentGroup, change music back
|
||||
public void EndGuildleveDirector()
|
||||
{
|
||||
foreach (Actor p in GetPlayerMembers())
|
||||
{
|
||||
Player player = (Player)p;
|
||||
player.ChangeMusic(player.GetZone().bgmDay);
|
||||
}
|
||||
}
|
||||
|
||||
public void SyncAllInfo()
|
||||
{
|
||||
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("guildleveWork/infoVariable", this);
|
||||
|
||||
if (guildleveWork.aimNum[0] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNum[0]");
|
||||
if (guildleveWork.aimNum[1] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNum[1]");
|
||||
if (guildleveWork.aimNum[2] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNum[2]");
|
||||
if (guildleveWork.aimNum[3] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNum[3]");
|
||||
|
||||
if (guildleveWork.aimNumNow[0] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNumNow[0]");
|
||||
if (guildleveWork.aimNumNow[1] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNumNow[1]");
|
||||
if (guildleveWork.aimNumNow[2] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNumNow[2]");
|
||||
if (guildleveWork.aimNumNow[3] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.aimNumNow[3]");
|
||||
|
||||
if (guildleveWork.uiState[0] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.uiState[0]");
|
||||
if (guildleveWork.uiState[1] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.uiState[1]");
|
||||
if (guildleveWork.uiState[2] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.uiState[2]");
|
||||
if (guildleveWork.uiState[3] != 0)
|
||||
propertyBuilder.AddProperty("guildleveWork.uiState[3]");
|
||||
|
||||
SendPacketsToPlayers(propertyBuilder.Done());
|
||||
}
|
||||
|
||||
public void UpdateAimNumNow(int index, sbyte value)
|
||||
{
|
||||
guildleveWork.aimNumNow[index] = value;
|
||||
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("guildleveWork/infoVariable", this);
|
||||
propertyBuilder.AddProperty(String.Format("guildleveWork.aimNumNow[{0}]", index));
|
||||
SendPacketsToPlayers(propertyBuilder.Done());
|
||||
}
|
||||
|
||||
public void UpdateUiState(int index, sbyte value)
|
||||
{
|
||||
guildleveWork.uiState[index] = value;
|
||||
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("guildleveWork/infoVariable", this);
|
||||
propertyBuilder.AddProperty(String.Format("guildleveWork.uiState[{0}]", index));
|
||||
SendPacketsToPlayers(propertyBuilder.Done());
|
||||
}
|
||||
|
||||
public void UpdateMarkers(int markerIndex, float x, float y, float z)
|
||||
{
|
||||
guildleveWork.markerX[markerIndex] = x;
|
||||
guildleveWork.markerY[markerIndex] = y;
|
||||
guildleveWork.markerZ[markerIndex] = z;
|
||||
ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("guildleveWork/marker", this);
|
||||
propertyBuilder.AddProperty(String.Format("guildleveWork.markerX[{0}]", markerIndex));
|
||||
propertyBuilder.AddProperty(String.Format("guildleveWork.markerY[{0}]", markerIndex));
|
||||
propertyBuilder.AddProperty(String.Format("guildleveWork.markerZ[{0}]", markerIndex));
|
||||
SendPacketsToPlayers(propertyBuilder.Done());
|
||||
}
|
||||
|
||||
public void SendPacketsToPlayers(List<SubPacket> packets)
|
||||
{
|
||||
List<Actor> players = GetPlayerMembers();
|
||||
foreach (Actor p in players)
|
||||
{
|
||||
((Player)p).QueuePackets(packets);
|
||||
}
|
||||
}
|
||||
|
||||
public static uint GlBorderIconIDToAnimID(uint iconId)
|
||||
{
|
||||
return iconId - 20000;
|
||||
}
|
||||
|
||||
public static uint GlPlateIconIDToAnimID(uint iconId)
|
||||
{
|
||||
return iconId - 20020;
|
||||
}
|
||||
|
||||
public static uint GetGLStartAnimationFromSheet(uint border, uint plate, bool isBoost)
|
||||
{
|
||||
return GetGLStartAnimation(GlBorderIconIDToAnimID(border), GlPlateIconIDToAnimID(plate), isBoost);
|
||||
}
|
||||
|
||||
public static uint GetGLStartAnimation(uint border, uint plate, bool isBoost)
|
||||
{
|
||||
uint borderBits = border;
|
||||
uint plateBits = plate << 7;
|
||||
|
||||
uint boostBits = isBoost ? (uint)0x8000 : (uint) 0;
|
||||
|
||||
return 0x0B000000 | boostBits | plateBits | borderBits;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director
|
||||
{
|
||||
class OpeningDirector : Director
|
||||
{
|
||||
public OpeningDirector(Player player, uint id) : base(player, id)
|
||||
{
|
||||
this.displayNameId = 0;
|
||||
this.customDisplayName = String.Format("openingDire_{0}_{1}", player.zone.zoneName, "04");
|
||||
|
||||
this.actorName = String.Format("openingDire_{0}_{1}@{2:x3}{3:x2}", player.zone.zoneName, "04", player.zoneId, 0);
|
||||
|
||||
this.actorName = this.actorName.Replace("Battle", "Btl");
|
||||
|
||||
this.className = "OpeningDirector";
|
||||
|
||||
this.eventConditions = new EventList();
|
||||
|
||||
List<EventList.NoticeEventCondition> noticeEventList = new List<EventList.NoticeEventCondition>();
|
||||
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
|
||||
|
||||
this.eventConditions.noticeEventConditions = noticeEventList;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/Director/OpeningDirector", false, false, false, false, 0x13881);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.Actors
|
||||
{
|
||||
class WeatherDirector : Director
|
||||
{
|
||||
private uint weatherId;
|
||||
|
||||
public WeatherDirector(Player player, uint weatherId)
|
||||
: base(player, 0x5FF80003)
|
||||
{
|
||||
this.weatherId = weatherId;
|
||||
|
||||
this.displayNameId = 0;
|
||||
|
||||
this.customDisplayName = String.Format("weatherDire_{0}_{1}", player.zone.zoneName, "07");
|
||||
|
||||
this.actorName = String.Format("weatherDire_{0}_{1}@{2:x3}{3:x2}", player.zone.zoneName, "04", player.zoneId, 0);
|
||||
|
||||
this.className = "Debug";
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/Director/Weather/WeatherDirector", false, false, false, false, weatherId);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
}
|
||||
|
||||
public override BasePacket GetSpawnPackets(uint playerActorId)
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director.Work
|
||||
{
|
||||
|
||||
class GuildleveWork
|
||||
{
|
||||
public uint startTime = 0;
|
||||
public sbyte[] aimNum = new sbyte[4];
|
||||
public sbyte[] aimNumNow = new sbyte[4];
|
||||
public sbyte[] uiState = new sbyte[4];
|
||||
public float[] markerX = new float[3];
|
||||
public float[] markerY = new float[3];
|
||||
public float[] markerZ = new float[3];
|
||||
public sbyte signal;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director
|
||||
{
|
||||
class QuestDirectorMan0g001 : Director
|
||||
{
|
||||
public QuestDirectorMan0g001(Player player, uint id)
|
||||
: base(player, id)
|
||||
{
|
||||
this.displayNameId = 0;
|
||||
this.customDisplayName = "questDirect_fst0Btl03_01";
|
||||
|
||||
this.actorName = "questDirect_fst0Btl03_01@0A615";
|
||||
this.className = "QuestDirectorMan0g001";
|
||||
|
||||
this.eventConditions = new EventList();
|
||||
|
||||
List<EventList.NoticeEventCondition> noticeEventList = new List<EventList.NoticeEventCondition>();
|
||||
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
|
||||
|
||||
this.eventConditions.noticeEventConditions = noticeEventList;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/Director/Quest/QuestDirectorMan0g001", false, false, false, false, false, 0x753A);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director
|
||||
{
|
||||
class QuestDirectorMan0l001 : Director
|
||||
{
|
||||
public QuestDirectorMan0l001(Player player, uint id)
|
||||
: base(player, id)
|
||||
{
|
||||
this.displayNameId = 0;
|
||||
this.customDisplayName = "questDirect_ocn0Btl02_01";
|
||||
|
||||
this.actorName = "questDirect_ocn0Btl02_01@0C196";
|
||||
this.className = "QuestDirectorMan0l001";
|
||||
|
||||
this.eventConditions = new EventList();
|
||||
|
||||
List<EventList.NoticeEventCondition> noticeEventList = new List<EventList.NoticeEventCondition>();
|
||||
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
|
||||
|
||||
this.eventConditions.noticeEventConditions = noticeEventList;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/Director/Quest/QuestDirectorMan0l001", false, false, false, false, false, 0x7532);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.packets;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.director
|
||||
{
|
||||
class QuestDirectorMan0u001 : Director
|
||||
{
|
||||
public QuestDirectorMan0u001(Player player, uint id)
|
||||
: base(player, id)
|
||||
{
|
||||
this.displayNameId = 0;
|
||||
this.customDisplayName = "questDirect_wil0Btl01_01";
|
||||
|
||||
this.actorName = "questDirect_wil0Btl01_01@0A615";
|
||||
this.className = "QuestDirectorMan0u001";
|
||||
|
||||
this.eventConditions = new EventList();
|
||||
|
||||
List<EventList.NoticeEventCondition> noticeEventList = new List<EventList.NoticeEventCondition>();
|
||||
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeEvent", 0xE, 0x0));
|
||||
noticeEventList.Add(new EventList.NoticeEventCondition("noticeRequest", 0x0, 0x1));
|
||||
|
||||
this.eventConditions.noticeEventConditions = noticeEventList;
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/Director/Quest/QuestDirectorMan0u001", false, false, false, false, false, 0x757F);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
}
|
||||
}
|
||||
}
|
173
FFXIVClassic Map Server/actors/group/ContentGroup.cs
Normal file
173
FFXIVClassic Map Server/actors/group/ContentGroup.cs
Normal file
|
@ -0,0 +1,173 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
using FFXIVClassic_Map_Server.actors.group.Work;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using FFXIVClassic_Map_Server.packets.send.groups;
|
||||
using FFXIVClassic_Map_Server.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group
|
||||
{
|
||||
class ContentGroup : Group
|
||||
{
|
||||
public ContentGroupWork contentGroupWork = new ContentGroupWork();
|
||||
private Director director;
|
||||
private List<uint> members = new List<uint>();
|
||||
private bool isStarted = false;
|
||||
|
||||
public ContentGroup(ulong groupIndex, Director director, uint[] initialMembers) : base(groupIndex)
|
||||
{
|
||||
if (initialMembers != null)
|
||||
{
|
||||
for (int i = 0; i < initialMembers.Length; i++)
|
||||
{
|
||||
Session s = Server.GetServer().GetSession(initialMembers[i]);
|
||||
if (s != null)
|
||||
s.GetActor().SetCurrentContentGroup(this);
|
||||
|
||||
members.Add(initialMembers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.director = director;
|
||||
contentGroupWork._globalTemp.director = (ulong)director.actorId << 32;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
isStarted = true;
|
||||
SendGroupPacketsAll(members);
|
||||
}
|
||||
|
||||
public void AddMember(Actor actor)
|
||||
{
|
||||
if (actor == null)
|
||||
return;
|
||||
|
||||
members.Add(actor.actorId);
|
||||
|
||||
if (actor is Character)
|
||||
((Character)actor).SetCurrentContentGroup(this);
|
||||
|
||||
if (isStarted)
|
||||
SendGroupPacketsAll(members);
|
||||
}
|
||||
|
||||
public void RemoveMember(uint memberId)
|
||||
{
|
||||
members.Remove(memberId);
|
||||
if (isStarted)
|
||||
SendGroupPacketsAll(members);
|
||||
CheckDestroy();
|
||||
}
|
||||
|
||||
public override List<GroupMember> BuildMemberList(uint id)
|
||||
{
|
||||
List<GroupMember> groupMembers = new List<GroupMember>();
|
||||
groupMembers.Add(new GroupMember(id, -1, 0, false, true, ""));
|
||||
foreach (uint charaId in members)
|
||||
{
|
||||
if (charaId != id)
|
||||
groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, ""));
|
||||
}
|
||||
return groupMembers;
|
||||
}
|
||||
|
||||
public override int GetMemberCount()
|
||||
{
|
||||
return members.Count;
|
||||
}
|
||||
|
||||
public override void SendInitWorkValues(Session session)
|
||||
{
|
||||
SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex);
|
||||
groupWork.addProperty(this, "contentGroupWork._globalTemp.director");
|
||||
groupWork.addByte(Utils.MurmurHash2("contentGroupWork.property[0]", 0), 1);
|
||||
groupWork.setTarget("/_init");
|
||||
|
||||
SubPacket test = groupWork.buildPacket(session.id, session.id);
|
||||
test.DebugPrintSubPacket();
|
||||
session.QueuePacket(test);
|
||||
}
|
||||
|
||||
public override void SendGroupPackets(Session session)
|
||||
{
|
||||
ulong time = Utils.MilisUnixTimeStampUTC();
|
||||
List<GroupMember> members = BuildMemberList(session.id);
|
||||
|
||||
session.QueuePacket(GroupHeaderPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
session.QueuePacket(GroupMembersBeginPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
|
||||
int currentIndex = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (GetMemberCount() - currentIndex >= 64)
|
||||
session.QueuePacket(ContentMembersX64Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else if (GetMemberCount() - currentIndex >= 32)
|
||||
session.QueuePacket(ContentMembersX32Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else if (GetMemberCount() - currentIndex >= 16)
|
||||
session.QueuePacket(ContentMembersX16Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else if (GetMemberCount() - currentIndex > 0)
|
||||
session.QueuePacket(ContentMembersX08Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
session.QueuePacket(GroupMembersEndPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
|
||||
}
|
||||
|
||||
public override uint GetTypeId()
|
||||
{
|
||||
return Group.ContentGroup_SimpleContentGroup24B;
|
||||
}
|
||||
|
||||
|
||||
public void SendAll()
|
||||
{
|
||||
SendGroupPacketsAll(members);
|
||||
}
|
||||
|
||||
public void DeleteGroup()
|
||||
{
|
||||
SendDeletePackets(members);
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
Session s = Server.GetServer().GetSession(members[i]);
|
||||
if (s != null)
|
||||
s.GetActor().SetCurrentContentGroup(null);
|
||||
Actor a = director.GetZone().FindActorInArea(members[i]);
|
||||
if (a is Npc)
|
||||
((Npc)a).Despawn();
|
||||
members.Remove(members[i]);
|
||||
i--;
|
||||
}
|
||||
Server.GetWorldManager().DeleteContentGroup(groupIndex);
|
||||
}
|
||||
|
||||
public void CheckDestroy()
|
||||
{
|
||||
bool foundSession = false;
|
||||
foreach (uint memberId in members)
|
||||
{
|
||||
Session session = Server.GetServer().GetSession(memberId);
|
||||
if (session != null)
|
||||
{
|
||||
foundSession = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSession)
|
||||
DeleteGroup();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
29
FFXIVClassic Map Server/actors/group/GLContentGroup.cs
Normal file
29
FFXIVClassic Map Server/actors/group/GLContentGroup.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.director;
|
||||
using FFXIVClassic_Map_Server.actors.group.Work;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using FFXIVClassic_Map_Server.packets.send.groups;
|
||||
using FFXIVClassic_Map_Server.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group
|
||||
{
|
||||
class GLContentGroup : ContentGroup
|
||||
{
|
||||
public GLContentGroup(ulong groupIndex, Director director, uint[] initialMembers)
|
||||
: base(groupIndex, director, initialMembers)
|
||||
{
|
||||
}
|
||||
|
||||
public override uint GetTypeId()
|
||||
{
|
||||
return Group.ContentGroup_GuildleveGroup;
|
||||
}
|
||||
}
|
||||
}
|
157
FFXIVClassic Map Server/actors/group/Group.cs
Normal file
157
FFXIVClassic Map Server/actors/group/Group.cs
Normal file
|
@ -0,0 +1,157 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using FFXIVClassic_Map_Server.packets.send.groups;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group
|
||||
{
|
||||
class Group
|
||||
{
|
||||
public const uint PlayerPartyGroup = 10001;
|
||||
public const uint CompanyGroup = 20002;
|
||||
|
||||
public const uint GroupInvitationRelationGroup = 50001;
|
||||
public const uint TradeRelationGroup = 50002;
|
||||
public const uint BazaarBuyItemRelationGroup = 50009;
|
||||
|
||||
public const uint RetainerGroup = 80001;
|
||||
|
||||
public const uint MonsterPartyGroup = 10002;
|
||||
|
||||
public const uint ContentGroup_GuildleveGroup = 30001;
|
||||
public const uint ContentGroup_PublicPopGroup = 30002;
|
||||
public const uint ContentGroup_SimpleContentGroup24A = 30003;
|
||||
public const uint ContentGroup_SimpleContentGroup32A = 30004;
|
||||
public const uint ContentGroup_SimpleContentGroup128 = 30005;
|
||||
public const uint ContentGroup_SimpleContentGroup24B = 30006;
|
||||
public const uint ContentGroup_SimpleContentGroup32B = 30007;
|
||||
public const uint ContentGroup_RetainerAccessGroup = 30008;
|
||||
public const uint ContentGroup_SimpleContentGroup99999 = 30009;
|
||||
public const uint ContentGroup_SimpleContentGroup512 = 30010;
|
||||
public const uint ContentGroup_SimpleContentGroup64A = 30011;
|
||||
public const uint ContentGroup_SimpleContentGroup64B = 30012;
|
||||
public const uint ContentGroup_SimpleContentGroup64C = 30013;
|
||||
public const uint ContentGroup_SimpleContentGroup64D = 30014;
|
||||
public const uint ContentGroup_SimpleContentGroup64E = 30015;
|
||||
public const uint ContentGroup_SimpleContentGroup64F = 30016;
|
||||
public const uint ContentGroup_SimpleContentGroup64G = 30017;
|
||||
public const uint ContentGroup_SimpleContentGroup24C = 30018;
|
||||
|
||||
public readonly ulong groupIndex;
|
||||
|
||||
public Group(ulong groupIndex)
|
||||
{
|
||||
this.groupIndex = groupIndex;
|
||||
}
|
||||
|
||||
public virtual int GetMemberCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual uint GetTypeId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual string GetGroupName()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public virtual int GetGroupLocalizedName()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public virtual List<GroupMember> BuildMemberList(uint id)
|
||||
{
|
||||
return new List<GroupMember>();
|
||||
}
|
||||
|
||||
public void SendGroupPacketsAll(params uint[] ids)
|
||||
{
|
||||
for (int i = 0; i < ids.Length; i++)
|
||||
{
|
||||
Session session = Server.GetServer().GetSession(ids[i]);
|
||||
|
||||
if (session != null)
|
||||
SendGroupPackets(session);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendGroupPacketsAll(List<uint> ids)
|
||||
{
|
||||
for (int i = 0; i < ids.Count; i++)
|
||||
{
|
||||
Session session = Server.GetServer().GetSession(ids[i]);
|
||||
|
||||
if (session != null)
|
||||
SendGroupPackets(session);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendDeletePackets(params uint[] ids)
|
||||
{
|
||||
for (int i = 0; i < ids.Length; i++)
|
||||
{
|
||||
Session session = Server.GetServer().GetSession(ids[i]);
|
||||
|
||||
if (session != null)
|
||||
SendDeletePacket(session);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendDeletePackets(List<uint> ids)
|
||||
{
|
||||
for (int i = 0; i < ids.Count; i++)
|
||||
{
|
||||
Session session = Server.GetServer().GetSession(ids[i]);
|
||||
|
||||
if (session != null)
|
||||
SendDeletePacket(session);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SendGroupPackets(Session session)
|
||||
{
|
||||
ulong time = Utils.MilisUnixTimeStampUTC();
|
||||
List<GroupMember> members = BuildMemberList(session.id);
|
||||
|
||||
session.QueuePacket(GroupHeaderPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
session.QueuePacket(GroupMembersBeginPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
|
||||
int currentIndex = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (GetMemberCount() - currentIndex >= 64)
|
||||
session.QueuePacket(GroupMembersX64Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else if (GetMemberCount() - currentIndex >= 32)
|
||||
session.QueuePacket(GroupMembersX32Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else if (GetMemberCount() - currentIndex >= 16)
|
||||
session.QueuePacket(GroupMembersX16Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else if (GetMemberCount() - currentIndex > 0)
|
||||
session.QueuePacket(GroupMembersX08Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
session.QueuePacket(GroupMembersEndPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
|
||||
|
||||
}
|
||||
|
||||
public void SendDeletePacket(Session session)
|
||||
{
|
||||
if (session != null)
|
||||
session.QueuePacket(DeleteGroupPacket.buildPacket(session.id, this));
|
||||
}
|
||||
|
||||
public virtual void SendInitWorkValues(Session session)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
63
FFXIVClassic Map Server/actors/group/MonsterParty.cs
Normal file
63
FFXIVClassic Map Server/actors/group/MonsterParty.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using FFXIVClassic_Map_Server.packets.send.groups;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group
|
||||
{
|
||||
class MonsterParty : Group
|
||||
{
|
||||
private List<uint> monsterMembers = new List<uint>();
|
||||
|
||||
public MonsterParty(ulong groupIndex, uint[] initialMonsterMembers)
|
||||
: base(groupIndex)
|
||||
{
|
||||
for (int i = 0; i < initialMonsterMembers.Length; i++)
|
||||
monsterMembers.Add(initialMonsterMembers[i]);
|
||||
}
|
||||
|
||||
public void AddMember(uint memberId)
|
||||
{
|
||||
monsterMembers.Add(memberId);
|
||||
SendGroupPacketsAll(monsterMembers);
|
||||
}
|
||||
|
||||
public void RemoveMember(uint memberId)
|
||||
{
|
||||
monsterMembers.Remove(memberId);
|
||||
SendGroupPacketsAll(monsterMembers);
|
||||
}
|
||||
|
||||
public override List<GroupMember> BuildMemberList(uint id)
|
||||
{
|
||||
List<GroupMember> groupMembers = new List<GroupMember>();
|
||||
groupMembers.Add(new GroupMember(id, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(id).customDisplayName));
|
||||
foreach (uint charaId in monsterMembers)
|
||||
{
|
||||
if (charaId != id)
|
||||
groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(charaId).customDisplayName));
|
||||
}
|
||||
return groupMembers;
|
||||
}
|
||||
|
||||
public override void SendInitWorkValues(Session session)
|
||||
{
|
||||
SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex);
|
||||
groupWork.setTarget("/_init");
|
||||
|
||||
SubPacket test = groupWork.buildPacket(session.id, session.id);
|
||||
session.QueuePacket(test);
|
||||
}
|
||||
|
||||
public override uint GetTypeId()
|
||||
{
|
||||
return Group.MonsterPartyGroup;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
74
FFXIVClassic Map Server/actors/group/Party.cs
Normal file
74
FFXIVClassic Map Server/actors/group/Party.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.group.Work;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group
|
||||
{
|
||||
class Party : Group
|
||||
{
|
||||
public PartyWork partyGroupWork = new PartyWork();
|
||||
public List<uint> members = new List<uint>();
|
||||
|
||||
public Party(ulong groupId, uint leaderCharaId) : base(groupId)
|
||||
{
|
||||
partyGroupWork._globalTemp.owner = (ulong)(((ulong)leaderCharaId << 32) | 0xB36F92);
|
||||
members.Add(leaderCharaId);
|
||||
}
|
||||
|
||||
public void SetLeader(uint actorId)
|
||||
{
|
||||
partyGroupWork._globalTemp.owner = (ulong)(((ulong)actorId << 32) | 0xB36F92);
|
||||
}
|
||||
|
||||
public uint GetLeader()
|
||||
{
|
||||
return (uint)(((ulong)partyGroupWork._globalTemp.owner >> 32) & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
public uint GetIdForName(string name)
|
||||
{
|
||||
for (int i = 0; i < members.Count; i++)
|
||||
{
|
||||
if (Server.GetWorldManager().GetActorInWorld(members[i]).customDisplayName.Equals(name))
|
||||
{
|
||||
return members[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool IsInParty(uint charaId)
|
||||
{
|
||||
return members.Contains(charaId);
|
||||
}
|
||||
|
||||
public override int GetMemberCount()
|
||||
{
|
||||
return members.Count;
|
||||
}
|
||||
|
||||
public override uint GetTypeId()
|
||||
{
|
||||
return Group.PlayerPartyGroup;
|
||||
}
|
||||
|
||||
public override List<GroupMember> BuildMemberList(uint id)
|
||||
{
|
||||
List<GroupMember> groupMembers = new List<GroupMember>();
|
||||
groupMembers.Add(new GroupMember(id, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(id).customDisplayName));
|
||||
foreach (uint charaId in members)
|
||||
{
|
||||
if (charaId != id)
|
||||
groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(charaId).customDisplayName));
|
||||
}
|
||||
return groupMembers;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
77
FFXIVClassic Map Server/actors/group/Relation.cs
Normal file
77
FFXIVClassic Map Server/actors/group/Relation.cs
Normal file
|
@ -0,0 +1,77 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.group.Work;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using FFXIVClassic_Map_Server.packets.send.group;
|
||||
using FFXIVClassic_Map_Server.packets.send.groups;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group
|
||||
{
|
||||
class Relation : Group
|
||||
{
|
||||
public RelationWork work = new RelationWork();
|
||||
private uint charaOther;
|
||||
private ulong topicGroup;
|
||||
|
||||
public Relation(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex)
|
||||
{
|
||||
this.charaOther = other;
|
||||
work._globalTemp.host = ((ulong)host << 32) | (0xc17909);
|
||||
work._globalTemp.variableCommand = command;
|
||||
this.topicGroup = topicGroup;
|
||||
}
|
||||
|
||||
public uint GetHost()
|
||||
{
|
||||
return (uint)(((ulong)work._globalTemp.host >> 32) & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
public uint GetOther()
|
||||
{
|
||||
return charaOther;
|
||||
}
|
||||
|
||||
public override int GetMemberCount()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public override uint GetTypeId()
|
||||
{
|
||||
return Group.GroupInvitationRelationGroup;
|
||||
}
|
||||
|
||||
public ulong GetTopicGroupIndex()
|
||||
{
|
||||
return topicGroup;
|
||||
}
|
||||
|
||||
public override List<GroupMember> BuildMemberList(uint id)
|
||||
{
|
||||
List<GroupMember> groupMembers = new List<GroupMember>();
|
||||
|
||||
uint hostId = (uint)((work._globalTemp.host >> 32) & 0xFFFFFFFF);
|
||||
|
||||
groupMembers.Add(new GroupMember(hostId, -1, 0, false, Server.GetServer().GetSession(hostId) != null, Server.GetWorldManager().GetActorInWorld(hostId).customDisplayName));
|
||||
groupMembers.Add(new GroupMember(charaOther, -1, 0, false, Server.GetServer().GetSession(charaOther) != null, Server.GetWorldManager().GetActorInWorld(charaOther).customDisplayName));
|
||||
return groupMembers;
|
||||
}
|
||||
|
||||
public override void SendInitWorkValues(Session session)
|
||||
{
|
||||
SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex);
|
||||
groupWork.addProperty(this, "work._globalTemp.host");
|
||||
groupWork.addProperty(this, "work._globalTemp.variableCommand");
|
||||
groupWork.setTarget("/_init");
|
||||
|
||||
SubPacket test = groupWork.buildPacket(session.id, session.id);
|
||||
test.DebugPrintSubPacket();
|
||||
session.QueuePacket(test);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class ContentGroupWork
|
||||
{
|
||||
public GlobalTemp _globalTemp = new GlobalTemp();
|
||||
public bool[] property = new bool[32];
|
||||
}
|
||||
}
|
12
FFXIVClassic Map Server/actors/group/work/GlobalTemp.cs
Normal file
12
FFXIVClassic Map Server/actors/group/work/GlobalTemp.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class GlobalTemp
|
||||
{
|
||||
public ulong director;
|
||||
}
|
||||
}
|
15
FFXIVClassic Map Server/actors/group/work/GroupGlobalSave.cs
Normal file
15
FFXIVClassic Map Server/actors/group/work/GroupGlobalSave.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class GroupGlobalSave
|
||||
{
|
||||
public ulong master;
|
||||
public ushort[] crestIcon = new ushort[4];
|
||||
public byte rank = 1;
|
||||
}
|
||||
}
|
20
FFXIVClassic Map Server/actors/group/work/GroupGlobalTemp.cs
Normal file
20
FFXIVClassic Map Server/actors/group/work/GroupGlobalTemp.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class GroupGlobalTemp
|
||||
{
|
||||
public ulong owner;
|
||||
|
||||
//For content group
|
||||
public ulong director;
|
||||
|
||||
//For relation group
|
||||
public ulong host;
|
||||
public uint variableCommand;
|
||||
}
|
||||
}
|
20
FFXIVClassic Map Server/actors/group/work/GroupMemberSave.cs
Normal file
20
FFXIVClassic Map Server/actors/group/work/GroupMemberSave.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class GroupMemberSave
|
||||
{
|
||||
//For LS
|
||||
public byte rank;
|
||||
|
||||
//For Retainers
|
||||
public byte cdIDOffset;
|
||||
public ushort placeName;
|
||||
public byte conditions;
|
||||
public byte level;
|
||||
}
|
||||
}
|
13
FFXIVClassic Map Server/actors/group/work/PartyWork.cs
Normal file
13
FFXIVClassic Map Server/actors/group/work/PartyWork.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class PartyWork
|
||||
{
|
||||
public GroupGlobalTemp _globalTemp = new GroupGlobalTemp();
|
||||
}
|
||||
}
|
13
FFXIVClassic Map Server/actors/group/work/RelationWork.cs
Normal file
13
FFXIVClassic Map Server/actors/group/work/RelationWork.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.actors.group.Work
|
||||
{
|
||||
class RelationWork
|
||||
{
|
||||
public GroupGlobalTemp _globalTemp = new GroupGlobalTemp();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -8,7 +9,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
class Quest : Actor
|
||||
{
|
||||
private Player owner;
|
||||
private int currentPhase = 0;
|
||||
private uint currentPhase = 0;
|
||||
private uint questFlags = 0;
|
||||
private Dictionary<string, Object> questData = new Dictionary<string, object>();
|
||||
|
||||
|
@ -18,7 +19,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
actorName = name;
|
||||
}
|
||||
|
||||
public Quest(Player owner, uint actorID, string name, string questDataJson, uint questFlags)
|
||||
public Quest(Player owner, uint actorID, string name, string questDataJson, uint questFlags, uint currentPhase)
|
||||
: base(actorID)
|
||||
{
|
||||
this.owner = owner;
|
||||
|
@ -32,6 +33,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
|
||||
if (questData == null)
|
||||
questData = new Dictionary<string, object>();
|
||||
|
||||
this.currentPhase = currentPhase;
|
||||
}
|
||||
|
||||
public void SetQuestData(string dataName, object data)
|
||||
|
@ -41,6 +44,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
//Inform update
|
||||
}
|
||||
|
||||
public uint GetQuestId()
|
||||
{
|
||||
return actorId & 0xFFFFF;
|
||||
}
|
||||
|
||||
public object GetQuestData(string dataName)
|
||||
{
|
||||
if (questData.ContainsKey(dataName))
|
||||
|
@ -54,11 +62,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
questData.Clear();
|
||||
}
|
||||
|
||||
public uint GetQuestId()
|
||||
{
|
||||
return actorId;
|
||||
}
|
||||
|
||||
public void ClearQuestFlags()
|
||||
{
|
||||
questFlags = 0;
|
||||
|
@ -79,7 +82,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
else
|
||||
questFlags &= (uint)~(1 << bitIndex);
|
||||
|
||||
//Inform update
|
||||
DoCompletionCheck();
|
||||
}
|
||||
|
||||
public bool GetQuestFlag(int bitIndex)
|
||||
|
@ -93,14 +96,18 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
return (questFlags & (1 << bitIndex)) == (1 << bitIndex);
|
||||
}
|
||||
|
||||
public int GetPhase()
|
||||
public uint GetPhase()
|
||||
{
|
||||
return currentPhase;
|
||||
}
|
||||
|
||||
public void NextPhase()
|
||||
public void NextPhase(uint phaseNumber)
|
||||
{
|
||||
currentPhase++;
|
||||
currentPhase = phaseNumber;
|
||||
owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25116, 0x20, (object)GetQuestId());
|
||||
SaveData();
|
||||
|
||||
DoCompletionCheck();
|
||||
}
|
||||
|
||||
public uint GetQuestFlags()
|
||||
|
@ -118,5 +125,21 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
Database.SaveQuest(owner, this);
|
||||
}
|
||||
|
||||
public void DoCompletionCheck()
|
||||
{
|
||||
List<LuaParam> returned = LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "isObjectivesComplete", true);
|
||||
if (returned != null && returned.Count >= 1 && returned[0].typeID == 3)
|
||||
{
|
||||
owner.SendDataPacket("attention", Server.GetWorldManager().GetActor(), "", 25225, (object)GetQuestId());
|
||||
owner.SendGameMessage(Server.GetWorldManager().GetActor(), 25225, 0x20, (object)GetQuestId());
|
||||
}
|
||||
}
|
||||
|
||||
public void DoAbandon()
|
||||
{
|
||||
LuaEngine.GetInstance().CallLuaFunctionForReturn(owner, this, "onAbandonQuest", true);
|
||||
owner.SendGameMessage(owner, Server.GetWorldManager().GetActor(), 25236, 0x20, (object)GetQuestId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -16,24 +17,24 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||
this.className = "WorldMaster";
|
||||
}
|
||||
|
||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
||||
public override SubPacket CreateScriptBindPacket()
|
||||
{
|
||||
List<LuaParam> lParams;
|
||||
lParams = LuaUtils.CreateLuaParamList("/World/WorldMaster_event", false, false, false, false, false, null);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
||||
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
|
||||
}
|
||||
|
||||
public override BasePacket GetSpawnPackets(uint playerActorId)
|
||||
public override List<SubPacket> GetSpawnPackets()
|
||||
{
|
||||
List<SubPacket> subpackets = new List<SubPacket>();
|
||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
||||
subpackets.Add(CreateNamePacket(playerActorId));
|
||||
subpackets.Add(CreateStatePacket(playerActorId));
|
||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
||||
return BasePacket.CreatePacket(subpackets, true, false);
|
||||
subpackets.Add(CreateAddActorPacket(0));
|
||||
subpackets.Add(CreateSpeedPacket());
|
||||
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||
subpackets.Add(CreateNamePacket());
|
||||
subpackets.Add(CreateStatePacket());
|
||||
subpackets.Add(CreateIsZoneingPacket());
|
||||
subpackets.Add(CreateScriptBindPacket());
|
||||
return subpackets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
61
FFXIVClassic Map Server/dataobjects/GuildleveData.cs
Normal file
61
FFXIVClassic Map Server/dataobjects/GuildleveData.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using MySql.Data.MySqlClient;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.dataobjects
|
||||
{
|
||||
class GuildleveData
|
||||
{
|
||||
public readonly uint id;
|
||||
public readonly uint classType;
|
||||
public readonly uint location;
|
||||
public readonly ushort factionCreditRequired;
|
||||
public readonly ushort level;
|
||||
public readonly uint aetheryte;
|
||||
public readonly uint plateId;
|
||||
public readonly uint borderId;
|
||||
public readonly uint objective;
|
||||
public readonly byte timeLimit;
|
||||
public readonly uint skill;
|
||||
public readonly byte favorCount;
|
||||
|
||||
public readonly sbyte[] aimNum = new sbyte[4];
|
||||
public readonly uint[] itemTarget = new uint[4];
|
||||
public readonly uint[] mobTarget = new uint[4];
|
||||
|
||||
public GuildleveData(MySqlDataReader reader)
|
||||
{
|
||||
id = reader.GetUInt32("id");
|
||||
classType = reader.GetUInt32("classType");
|
||||
location = reader.GetUInt32("location");
|
||||
factionCreditRequired = reader.GetUInt16("factionCreditRequired");
|
||||
level = reader.GetUInt16("level");
|
||||
aetheryte = reader.GetUInt32("aetheryte");
|
||||
plateId = reader.GetUInt32("plateId");
|
||||
borderId = reader.GetUInt32("borderId");
|
||||
objective = reader.GetUInt32("objective");
|
||||
timeLimit = reader.GetByte("timeLimit");
|
||||
skill = reader.GetUInt32("skill");
|
||||
favorCount = reader.GetByte("favorCount");
|
||||
|
||||
aimNum[0] = reader.GetSByte("aimNum1");
|
||||
aimNum[1] = reader.GetSByte("aimNum2");
|
||||
aimNum[2] = reader.GetSByte("aimNum3");
|
||||
aimNum[3] = reader.GetSByte("aimNum4");
|
||||
|
||||
itemTarget[0] = reader.GetUInt32("item1");
|
||||
itemTarget[1] = reader.GetUInt32("item2");
|
||||
itemTarget[2] = reader.GetUInt32("item3");
|
||||
itemTarget[3] = reader.GetUInt32("item4");
|
||||
|
||||
mobTarget[0] = reader.GetUInt32("mob1");
|
||||
mobTarget[1] = reader.GetUInt32("mob2");
|
||||
mobTarget[2] = reader.GetUInt32("mob3");
|
||||
mobTarget[3] = reader.GetUInt32("mob4");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
this.quantity = 1;
|
||||
this.slot = slot;
|
||||
|
||||
Item gItem = Server.GetItemGamedata(itemId);
|
||||
ItemData gItem = Server.GetItemGamedata(itemId);
|
||||
itemType = gItem.isExclusive ? (byte)0x3 : (byte)0x0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ using System;
|
|||
|
||||
namespace FFXIVClassic_Map_Server.dataobjects
|
||||
{
|
||||
class Item
|
||||
class ItemData
|
||||
{
|
||||
//Basic
|
||||
public readonly uint catalogID;
|
||||
|
@ -39,7 +39,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
public readonly int repairLevel;
|
||||
public readonly int repairLicense;
|
||||
|
||||
public Item(MySqlDataReader reader)
|
||||
public ItemData(MySqlDataReader reader)
|
||||
{
|
||||
catalogID = reader.GetUInt32("catalogID");
|
||||
name = reader.GetString("name");
|
||||
|
@ -50,6 +50,8 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
isExclusive = reader.GetBoolean("isExclusive");
|
||||
|
||||
durability = reader.GetInt32("durability");
|
||||
sellPrice = reader.GetInt32("sellPrice");
|
||||
|
||||
icon = reader.GetInt32("icon");
|
||||
kind = reader.GetInt32("kind");
|
||||
rarity = reader.GetInt32("rarity");
|
||||
|
@ -387,7 +389,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
|
||||
}
|
||||
|
||||
class EquipmentItem : Item
|
||||
class EquipmentItem : ItemData
|
||||
{
|
||||
//graphics
|
||||
public readonly uint graphicsWeaponId;
|
||||
|
@ -467,6 +469,11 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
|
||||
class WeaponItem : EquipmentItem
|
||||
{
|
||||
//extra graphics
|
||||
public readonly uint graphicsOffhandWeaponId;
|
||||
public readonly uint graphicsOffhandEquipmentId;
|
||||
public readonly uint graphicsOffhandVariantId;
|
||||
|
||||
//weapon sheet
|
||||
public readonly short attack;
|
||||
public readonly short magicAttack;
|
||||
|
@ -497,6 +504,13 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
public WeaponItem(MySqlDataReader reader)
|
||||
: base(reader)
|
||||
{
|
||||
if (!reader.IsDBNull(reader.GetOrdinal("offHandWeaponId")) && !reader.IsDBNull(reader.GetOrdinal("offHandEquipmentId")) && !reader.IsDBNull(reader.GetOrdinal("offHandVarientId")))
|
||||
{
|
||||
graphicsOffhandWeaponId = reader.GetUInt32("offHandWeaponId");
|
||||
graphicsOffhandEquipmentId = reader.GetUInt32("offHandEquipmentId");
|
||||
graphicsOffhandVariantId = reader.GetUInt32("offHandVarientId");
|
||||
}
|
||||
|
||||
attack = reader.GetInt16("attack");
|
||||
magicAttack = reader.GetInt16("magicAttack");
|
||||
craftProcessing = reader.GetInt16("craftProcessing");
|
|
@ -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,34 @@ 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);
|
||||
actorInstanceList.Add(playerActor);
|
||||
this.id = sessionId;
|
||||
playerActor = new Player(this, sessionId);
|
||||
}
|
||||
|
||||
public void SetConnection(int type, ClientConnection conn)
|
||||
public void QueuePacket(List<SubPacket> packets)
|
||||
{
|
||||
conn.connType = type;
|
||||
switch (type)
|
||||
{
|
||||
case BasePacket.TYPE_ZONE:
|
||||
zoneConnection = conn;
|
||||
break;
|
||||
case BasePacket.TYPE_CHAT:
|
||||
chatConnection = conn;
|
||||
break;
|
||||
}
|
||||
foreach (SubPacket s in packets)
|
||||
QueuePacket(s);
|
||||
}
|
||||
|
||||
public bool IsClientConnectionsReady()
|
||||
public void QueuePacket(SubPacket subPacket)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public void QueuePacket(SubPacket subPacket, bool isAuthed, bool isEncrypted)
|
||||
{
|
||||
zoneConnection.QueuePacket(subPacket, isAuthed, isEncrypted);
|
||||
subPacket.SetTargetId(id);
|
||||
Server.GetWorldConnection().QueuePacket(subPacket);
|
||||
}
|
||||
|
||||
public Player GetActor()
|
||||
|
@ -98,6 +66,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;
|
||||
|
@ -109,12 +80,15 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
playerActor.rotation = rot;
|
||||
playerActor.moveState = moveState;
|
||||
|
||||
GetActor().zone.UpdateActorPosition(GetActor());
|
||||
GetActor().GetZone().UpdateActorPosition(GetActor());
|
||||
|
||||
}
|
||||
|
||||
long lastMilis = 0;
|
||||
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>();
|
||||
|
@ -124,7 +98,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
{
|
||||
if (!list.Contains(actorInstanceList[i]))
|
||||
{
|
||||
GetActor().QueuePacket(RemoveActorPacket.BuildPacket(playerActor.actorId, actorInstanceList[i].actorId));
|
||||
QueuePacket(RemoveActorPacket.BuildPacket(actorInstanceList[i].actorId));
|
||||
actorInstanceList.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
@ -139,13 +113,18 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
|
||||
if (actorInstanceList.Contains(actor))
|
||||
{
|
||||
GetActor().QueuePacket(actor.CreatePositionUpdatePacket(playerActor.actorId));
|
||||
//Don't send for static characters (npcs)
|
||||
if (actor is Character && ((Character)actor).isStatic)
|
||||
continue;
|
||||
|
||||
QueuePacket(actor.CreatePositionUpdatePacket());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetActor().QueuePacket(actor.GetSpawnPackets(playerActor.actorId, 1));
|
||||
GetActor().QueuePacket(actor.GetInitPackets(playerActor.actorId));
|
||||
GetActor().QueuePacket(actor.GetSetEventStatusPackets(playerActor.actorId));
|
||||
QueuePacket(actor.GetSpawnPackets(playerActor, 1));
|
||||
|
||||
QueuePacket(actor.GetInitPackets());
|
||||
QueuePacket(actor.GetSetEventStatusPackets());
|
||||
actorInstanceList.Add(actor);
|
||||
|
||||
if (actor is Npc)
|
||||
|
@ -163,5 +142,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||
actorInstanceList.Clear();
|
||||
}
|
||||
|
||||
|
||||
public void LockUpdates(bool f)
|
||||
{
|
||||
isUpdatesLocked = f;
|
||||
}
|
||||
}
|
||||
}
|
67
FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
Normal file
67
FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
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(SubPacket subpacket)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,200 +13,425 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using FFXIVClassic_Map_Server.lua;
|
||||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.actors.area;
|
||||
using System.Threading;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.lua
|
||||
{
|
||||
class LuaEngine
|
||||
{
|
||||
const string FILEPATH_PLAYER = "./scripts/player.lua";
|
||||
const string FILEPATH_ZONE = "./scripts/zones/{0}/zone.lua";
|
||||
const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua";
|
||||
const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua";
|
||||
const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.lua";
|
||||
public const string FILEPATH_PLAYER = "./scripts/player.lua";
|
||||
public const string FILEPATH_ZONE = "./scripts/unique/{0}/zone.lua";
|
||||
public const string FILEPATH_CONTENT = "./scripts/content/{0}.lua";
|
||||
public const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua";
|
||||
public const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua";
|
||||
public const string FILEPATH_NPCS = "./scripts/unique/{0}/{1}/{2}.lua";
|
||||
public const string FILEPATH_QUEST = "./scripts/quests/{0}/{1}.lua";
|
||||
|
||||
public LuaEngine()
|
||||
private static LuaEngine mThisEngine;
|
||||
private Dictionary<Coroutine, ulong> mSleepingOnTime = new Dictionary<Coroutine, ulong>();
|
||||
private Dictionary<string, List<Coroutine>> mSleepingOnSignal = new Dictionary<string, List<Coroutine>>();
|
||||
private Dictionary<uint, Coroutine> mSleepingOnPlayerEvent = new Dictionary<uint, Coroutine>();
|
||||
|
||||
private Timer luaTimer;
|
||||
|
||||
|
||||
private LuaEngine()
|
||||
{
|
||||
UserData.RegistrationPolicy = InteropRegistrationPolicy.Automatic;
|
||||
|
||||
luaTimer = new Timer(new TimerCallback(PulseSleepingOnTime),
|
||||
null, TimeSpan.Zero, TimeSpan.FromMilliseconds(50));
|
||||
}
|
||||
|
||||
public static List<LuaParam> DoActorInstantiate(Player player, Actor target)
|
||||
public static LuaEngine GetInstance()
|
||||
{
|
||||
string luaPath;
|
||||
if (mThisEngine == null)
|
||||
mThisEngine = new LuaEngine();
|
||||
|
||||
if (target is Npc)
|
||||
{
|
||||
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
return mThisEngine;
|
||||
}
|
||||
|
||||
if (script == null)
|
||||
public void AddWaitCoroutine(Coroutine coroutine, float seconds)
|
||||
{
|
||||
ulong time = Utils.MilisUnixTimeStampUTC() + (ulong)(seconds * 1000);
|
||||
mSleepingOnTime.Add(coroutine, time);
|
||||
}
|
||||
|
||||
public void AddWaitSignalCoroutine(Coroutine coroutine, string signal)
|
||||
{
|
||||
if (!mSleepingOnSignal.ContainsKey(signal))
|
||||
mSleepingOnSignal.Add(signal, new List<Coroutine>());
|
||||
mSleepingOnSignal[signal].Add(coroutine);
|
||||
}
|
||||
|
||||
public void AddWaitEventCoroutine(Player player, Coroutine coroutine)
|
||||
{
|
||||
if (!mSleepingOnPlayerEvent.ContainsKey(player.actorId))
|
||||
mSleepingOnPlayerEvent.Add(player.actorId, coroutine);
|
||||
}
|
||||
|
||||
public void PulseSleepingOnTime(object state)
|
||||
{
|
||||
ulong currentTime = Utils.MilisUnixTimeStampUTC();
|
||||
List<Coroutine> mToAwake = new List<Coroutine>();
|
||||
|
||||
foreach (KeyValuePair<Coroutine, ulong> entry in mSleepingOnTime)
|
||||
{
|
||||
if (entry.Value <= currentTime)
|
||||
mToAwake.Add(entry.Key);
|
||||
}
|
||||
|
||||
foreach (Coroutine key in mToAwake)
|
||||
{
|
||||
mSleepingOnTime.Remove(key);
|
||||
DynValue value = key.Resume();
|
||||
ResolveResume(null, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSignal(string signal)
|
||||
{
|
||||
List<Coroutine> mToAwake = new List<Coroutine>();
|
||||
|
||||
if (mSleepingOnSignal.ContainsKey(signal))
|
||||
{
|
||||
mToAwake.AddRange(mSleepingOnSignal[signal]);
|
||||
mSleepingOnSignal.Remove(signal);
|
||||
}
|
||||
|
||||
foreach (Coroutine key in mToAwake)
|
||||
{
|
||||
DynValue value = key.Resume();
|
||||
ResolveResume(null, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEventUpdate(Player player, List<LuaParam> args)
|
||||
{
|
||||
if (mSleepingOnPlayerEvent.ContainsKey(player.actorId))
|
||||
{
|
||||
try
|
||||
{
|
||||
Coroutine coroutine = mSleepingOnPlayerEvent[player.actorId];
|
||||
mSleepingOnPlayerEvent.Remove(player.actorId);
|
||||
DynValue value = coroutine.Resume(LuaUtils.CreateLuaParamObjectList(args));
|
||||
ResolveResume(player, coroutine, value);
|
||||
}
|
||||
catch (ScriptRuntimeException e)
|
||||
{
|
||||
LuaEngine.SendError(player, String.Format("OnEventUpdated: {0}", e.DecoratedMessage));
|
||||
player.EndEvent();
|
||||
}
|
||||
}
|
||||
else
|
||||
player.EndEvent();
|
||||
}
|
||||
|
||||
private static string GetScriptPath(Actor target)
|
||||
{
|
||||
if (target is Player)
|
||||
{
|
||||
return String.Format(FILEPATH_PLAYER);
|
||||
}
|
||||
else if (target is Npc)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (target is Command)
|
||||
{
|
||||
return String.Format(FILEPATH_COMMANDS, target.GetName());
|
||||
}
|
||||
else if (target is Director)
|
||||
{
|
||||
return String.Format(FILEPATH_DIRECTORS, ((Director)target).GetScriptPath());
|
||||
}
|
||||
else if (target is PrivateAreaContent)
|
||||
{
|
||||
return String.Format(FILEPATH_CONTENT, ((PrivateAreaContent)target).GetPrivateAreaName());
|
||||
}
|
||||
else if (target is Area)
|
||||
{
|
||||
return String.Format(FILEPATH_ZONE, ((Area)target).zoneName);
|
||||
}
|
||||
else if (target is Quest)
|
||||
{
|
||||
string initial = ((Quest)target).actorName.Substring(0, 3);
|
||||
string questName = ((Quest)target).actorName;
|
||||
return String.Format(FILEPATH_QUEST, initial, questName);
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
private List<LuaParam> CallLuaFunctionNpcForReturn(Player player, Npc target, string funcName, bool optional, params object[] args)
|
||||
{
|
||||
object[] args2 = new object[args.Length + (player == null ? 1 : 2)];
|
||||
Array.Copy(args, 0, args2, (player == null ? 1 : 2), args.Length);
|
||||
if (player != null)
|
||||
{
|
||||
args2[0] = player;
|
||||
args2[1] = target;
|
||||
}
|
||||
else
|
||||
args2[0] = target;
|
||||
|
||||
LuaScript parent = null, child = null;
|
||||
|
||||
if (File.Exists("./scripts/base/" + target.classPath + ".lua"))
|
||||
parent = LuaEngine.LoadScript("./scripts/base/" + target.classPath + ".lua");
|
||||
|
||||
Area area = target.zone;
|
||||
if (area is PrivateArea)
|
||||
{
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/privatearea/{1}_{2}/{3}/{4}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), ((PrivateArea)area).GetPrivateAreaType(), target.className, target.GetUniqueId())))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/privatearea/{1}_{2}/{3}/{4}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), ((PrivateArea)area).GetPrivateAreaType(), target.className, target.GetUniqueId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId())))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId()));
|
||||
}
|
||||
|
||||
if (parent == null && child == null)
|
||||
{
|
||||
LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
||||
}
|
||||
|
||||
//Run Script
|
||||
DynValue result;
|
||||
|
||||
if (child != null && child.Globals[funcName] != null)
|
||||
result = child.Call(child.Globals[funcName], args2);
|
||||
else if (parent != null && parent.Globals[funcName] != null)
|
||||
result = parent.Call(parent.Globals[funcName], args2);
|
||||
else
|
||||
return null;
|
||||
|
||||
DynValue result = script.Call(script.Globals["init"], target);
|
||||
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||
return lparams;
|
||||
}
|
||||
|
||||
private void CallLuaFunctionNpc(Player player, Npc target, string funcName, bool optional, params object[] args)
|
||||
{
|
||||
object[] args2 = new object[args.Length + (player == null ? 1:2)];
|
||||
Array.Copy(args, 0, args2, (player == null ? 1 : 2), args.Length);
|
||||
if (player != null)
|
||||
{
|
||||
args2[0] = player;
|
||||
args2[1] = target;
|
||||
}
|
||||
else
|
||||
args2[0] = target;
|
||||
|
||||
LuaScript parent = null, child = null;
|
||||
|
||||
if (File.Exists("./scripts/base/" + target.classPath + ".lua"))
|
||||
parent = LuaEngine.LoadScript("./scripts/base/" + target.classPath + ".lua");
|
||||
|
||||
Area area = target.zone;
|
||||
if (area is PrivateArea)
|
||||
{
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/privatearea/{1}_{2}/{3}/{4}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), ((PrivateArea)area).GetPrivateAreaType(), target.className, target.GetUniqueId())))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/privatearea/{1}_{2}/{3}/{4}.lua", area.zoneName, ((PrivateArea)area).GetPrivateAreaName(), ((PrivateArea)area).GetPrivateAreaType(), target.className, target.GetUniqueId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (File.Exists(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId())))
|
||||
child = LuaEngine.LoadScript(String.Format("./scripts/unique/{0}/{1}/{2}.lua", area.zoneName, target.className, target.GetUniqueId()));
|
||||
}
|
||||
|
||||
if (parent == null && child == null)
|
||||
{
|
||||
LuaEngine.SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
|
||||
return;
|
||||
}
|
||||
|
||||
//Run Script
|
||||
Coroutine coroutine = null;
|
||||
|
||||
if (child != null && !child.Globals.Get(funcName).IsNil())
|
||||
coroutine = child.CreateCoroutine(child.Globals[funcName]).Coroutine;
|
||||
else if (parent != null && parent.Globals.Get(funcName) != null && !parent.Globals.Get(funcName).IsNil())
|
||||
coroutine = parent.CreateCoroutine(parent.Globals[funcName]).Coroutine;
|
||||
|
||||
if (coroutine != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
DynValue value = coroutine.Resume(args2);
|
||||
ResolveResume(player, coroutine, value);
|
||||
}
|
||||
catch (ScriptRuntimeException e)
|
||||
{
|
||||
SendError(player, e.DecoratedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<LuaParam> CallLuaFunctionForReturn(Player player, Actor target, string funcName, bool optional, params object[] args)
|
||||
{
|
||||
//Need a seperate case for NPCs cause that child/parent thing.
|
||||
if (target is Npc)
|
||||
return CallLuaFunctionNpcForReturn(player, (Npc)target, funcName, optional, args);
|
||||
|
||||
object[] args2 = new object[args.Length + (player == null ? 1 : 2)];
|
||||
Array.Copy(args, 0, args2, (player == null ? 1 : 2), args.Length);
|
||||
if (player != null)
|
||||
{
|
||||
args2[0] = player;
|
||||
args2[1] = target;
|
||||
}
|
||||
else
|
||||
args2[0] = target;
|
||||
|
||||
string luaPath = GetScriptPath(target);
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
if (script != null)
|
||||
{
|
||||
if (!script.Globals.Get(funcName).IsNil())
|
||||
{
|
||||
//Run Script
|
||||
DynValue result = script.Call(script.Globals[funcName], args2);
|
||||
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||
return lparams;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
||||
return null;
|
||||
if (!optional)
|
||||
SendError(player, String.Format("Could not find function '{0}' for actor {1}.", funcName, target.GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart)
|
||||
{
|
||||
string luaPath;
|
||||
|
||||
if (target is Command)
|
||||
{
|
||||
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName());
|
||||
}
|
||||
else if (target is Director)
|
||||
{
|
||||
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
|
||||
}
|
||||
else
|
||||
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
||||
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
if (!optional)
|
||||
SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<LuaParam> CallLuaFunctionForReturn(string path, string funcName, bool optional, params object[] args)
|
||||
{
|
||||
string luaPath = path;
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
|
||||
if (script == null)
|
||||
return null;
|
||||
|
||||
if (!script.Globals.Get("onEventStarted").IsNil())
|
||||
return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
if (script != null)
|
||||
{
|
||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void DoActorOnSpawn(Player player, Npc target)
|
||||
if (!script.Globals.Get(funcName).IsNil())
|
||||
{
|
||||
string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
||||
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onSpawn").IsNil())
|
||||
script.Call(script.Globals["onSpawn"], player, target);
|
||||
DynValue result = script.Call(script.Globals[funcName], args);
|
||||
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||
return lparams;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate)
|
||||
public void CallLuaFunction(Player player, Actor target, string funcName, bool optional, params object[] args)
|
||||
{
|
||||
//Need a seperate case for NPCs cause that child/parent thing.
|
||||
if (target is Npc)
|
||||
{
|
||||
((Npc)target).DoEventUpdate(player, eventUpdate);
|
||||
CallLuaFunctionNpc(player, (Npc)target, funcName, optional, args);
|
||||
return;
|
||||
}
|
||||
|
||||
string luaPath;
|
||||
object[] args2 = new object[args.Length + 2];
|
||||
Array.Copy(args, 0, args2, 2, args.Length);
|
||||
args2[0] = player;
|
||||
args2[1] = target;
|
||||
|
||||
if (target is Command)
|
||||
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName());
|
||||
else if (target is Director)
|
||||
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
|
||||
else
|
||||
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
||||
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
string luaPath = GetScriptPath(target);
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Have to Do this to combine LuaParams
|
||||
List<Object> objects = new List<Object>();
|
||||
objects.Add(player);
|
||||
objects.Add(target);
|
||||
objects.Add(eventUpdate.val2);
|
||||
objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams));
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onEventUpdate").IsNil())
|
||||
script.Call(script.Globals["onEventUpdate"], objects.ToArray());
|
||||
if (script != null)
|
||||
{
|
||||
if (!script.Globals.Get(funcName).IsNil())
|
||||
{
|
||||
Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
|
||||
DynValue value = coroutine.Resume(args2);
|
||||
ResolveResume(player, coroutine, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
||||
if (!optional)
|
||||
SendError(player, String.Format("Could not find function '{0}' for actor {1}.", funcName, target.GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnZoneIn(Player player)
|
||||
else
|
||||
{
|
||||
string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId);
|
||||
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onZoneIn").IsNil())
|
||||
script.Call(script.Globals["onZoneIn"], player);
|
||||
if (!(target is Area) && !optional)
|
||||
SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnBeginLogin(Player player)
|
||||
public void EventStarted(Player player, Actor target, EventStartPacket eventStart)
|
||||
{
|
||||
if (File.Exists(FILEPATH_PLAYER))
|
||||
List<LuaParam> lparams = eventStart.luaParams;
|
||||
lparams.Insert(0, new LuaParam(2, eventStart.triggerName));
|
||||
if (mSleepingOnPlayerEvent.ContainsKey(player.actorId))
|
||||
{
|
||||
LuaScript script = LoadScript(FILEPATH_PLAYER);
|
||||
Coroutine coroutine = mSleepingOnPlayerEvent[player.actorId];
|
||||
mSleepingOnPlayerEvent.Remove(player.actorId);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onBeginLogin").IsNil())
|
||||
script.Call(script.Globals["onBeginLogin"], player);
|
||||
try{
|
||||
DynValue value = coroutine.Resume();
|
||||
ResolveResume(null, coroutine, value);
|
||||
}
|
||||
catch (ScriptRuntimeException e)
|
||||
{
|
||||
LuaEngine.SendError(player, String.Format("OnEventStarted: {0}", e.DecoratedMessage));
|
||||
player.EndEvent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target is Director)
|
||||
((Director)target).OnEventStart(player, LuaUtils.CreateLuaParamObjectList(lparams));
|
||||
else
|
||||
CallLuaFunction(player, target, "onEventStarted", false, LuaUtils.CreateLuaParamObjectList(lparams));
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnLogin(Player player)
|
||||
public DynValue ResolveResume(Player player, Coroutine coroutine, DynValue value)
|
||||
{
|
||||
if (File.Exists(FILEPATH_PLAYER))
|
||||
if (value == null || value.IsVoid())
|
||||
return value;
|
||||
|
||||
if (player != null && value.String != null && value.String.Equals("_WAIT_EVENT"))
|
||||
{
|
||||
LuaScript script = LoadScript(FILEPATH_PLAYER);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onLogin").IsNil())
|
||||
script.Call(script.Globals["onLogin"], player);
|
||||
GetInstance().AddWaitEventCoroutine(player, coroutine);
|
||||
}
|
||||
else if (value.Tuple != null && value.Tuple.Length >= 1 && value.Tuple[0].String != null)
|
||||
{
|
||||
switch (value.Tuple[0].String)
|
||||
{
|
||||
case "_WAIT_TIME":
|
||||
GetInstance().AddWaitCoroutine(coroutine, (float)value.Tuple[1].Number);
|
||||
break;
|
||||
case "_WAIT_SIGNAL":
|
||||
GetInstance().AddWaitSignalCoroutine(coroutine, (string)value.Tuple[1].String);
|
||||
break;
|
||||
case "_WAIT_EVENT":
|
||||
GetInstance().AddWaitEventCoroutine((Player)value.Tuple[1].UserData.Object, coroutine);
|
||||
break;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#region RunGMCommand
|
||||
public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false)
|
||||
{
|
||||
bool playerNull = player == null;
|
||||
if (playerNull && param.Length >= 3)
|
||||
player = Server.GetWorldManager().GetPCInWorld(param[1] + " " + param[2]);
|
||||
|
||||
// load from scripts/commands/gm/ directory
|
||||
var path = String.Format("./scripts/commands/gm/{0}.lua", cmd.ToString().ToLower());
|
||||
var path = String.Format("./scripts/commands/gm/{0}.lua", cmd.ToLower());
|
||||
|
||||
// check if the file exists
|
||||
if (File.Exists(path))
|
||||
|
@ -290,7 +515,7 @@ namespace FFXIVClassic_Map_Server.lua
|
|||
// we'll push our lua params here
|
||||
List<object> LuaParam = new List<object>();
|
||||
|
||||
var i = 0;
|
||||
var i = playerNull ? 2 : 0;
|
||||
for (; i < parameters.Length; ++i)
|
||||
{
|
||||
try
|
||||
|
@ -326,10 +551,14 @@ namespace FFXIVClassic_Map_Server.lua
|
|||
// the script can double check the player exists, we'll push them anyways
|
||||
LuaParam.Insert(0, player);
|
||||
// push the arg count too
|
||||
LuaParam.Insert(1, i);
|
||||
LuaParam.Insert(1, i - (playerNull ? 2 : 0));
|
||||
|
||||
// run the script
|
||||
script.Call(script.Globals["onTrigger"], LuaParam.ToArray());
|
||||
//script.Call(script.Globals["onTrigger"], LuaParam.ToArray());
|
||||
|
||||
Coroutine coroutine = script.CreateCoroutine(script.Globals["onTrigger"]).Coroutine;
|
||||
DynValue value = coroutine.Resume(LuaParam.ToArray());
|
||||
GetInstance().ResolveResume(player, coroutine, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -338,17 +567,20 @@ namespace FFXIVClassic_Map_Server.lua
|
|||
}
|
||||
#endregion
|
||||
|
||||
public static LuaScript LoadScript(string filename)
|
||||
public static LuaScript LoadScript(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
return null;
|
||||
|
||||
LuaScript script = LoadGlobals();
|
||||
|
||||
try
|
||||
{
|
||||
script.DoFile(filename);
|
||||
script.DoFile(path);
|
||||
}
|
||||
catch (SyntaxErrorException e)
|
||||
{
|
||||
Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage);
|
||||
Program.Log.Error("{0}.", e.DecoratedMessage);
|
||||
return null;
|
||||
}
|
||||
return script;
|
||||
|
@ -362,8 +594,11 @@ namespace FFXIVClassic_Map_Server.lua
|
|||
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
|
||||
script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
|
||||
script.Globals["GetStaticActor"] = (Func<string, Actor>)Server.GetStaticActors;
|
||||
script.Globals["GetStaticActorById"] = (Func<uint, Actor>)Server.GetStaticActors;
|
||||
script.Globals["GetWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
|
||||
script.Globals["GetItemGamedata"] = (Func<uint, Item>)Server.GetItemGamedata;
|
||||
script.Globals["GetItemGamedata"] = (Func<uint, ItemData>)Server.GetItemGamedata;
|
||||
script.Globals["GetGuildleveGamedata"] = (Func<uint, GuildleveData>)Server.GetGuildleveGamedata;
|
||||
script.Globals["GetLuaInstance"] = (Func<LuaEngine>)LuaEngine.GetInstance;
|
||||
|
||||
script.Options.DebugPrint = s => { Program.Log.Debug(s); };
|
||||
return script;
|
||||
|
@ -371,53 +606,14 @@ namespace FFXIVClassic_Map_Server.lua
|
|||
|
||||
public static void SendError(Player player, string message)
|
||||
{
|
||||
message = "[LuaError] " + message;
|
||||
if (player == null)
|
||||
return;
|
||||
List<SubPacket> SendError = new List<SubPacket>();
|
||||
SendError.Add(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName));
|
||||
player.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "", message);
|
||||
player.playerSession.QueuePacket(BasePacket.CreatePacket(SendError, true, false));
|
||||
player.QueuePacket(EndEventPacket.BuildPacket(player.actorId, player.currentEventOwner, player.currentEventName));
|
||||
}
|
||||
|
||||
|
||||
internal static void DoDirectorOnTalked(Director director, Player player, Npc npc)
|
||||
{
|
||||
string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName());
|
||||
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onTalked").IsNil())
|
||||
script.Call(script.Globals["onTalked"], player, npc);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DoDirectorOnCommand(Director director, Player player, Command command)
|
||||
{
|
||||
string luaPath = String.Format(FILEPATH_DIRECTORS, director.GetName());
|
||||
|
||||
if (File.Exists(luaPath))
|
||||
{
|
||||
LuaScript script = LoadScript(luaPath);
|
||||
|
||||
if (script == null)
|
||||
return;
|
||||
|
||||
//Run Script
|
||||
if (!script.Globals.Get("onCommand").IsNil())
|
||||
script.Call(script.Globals["onCommand"], player, command);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendError(player, String.Format("ERROR: Could not find script for director {0}.", director.GetName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
namespace FFXIVClassic_Map_Server.lua
|
||||
{
|
||||
class LuaEvent
|
||||
{
|
||||
public static void GetStep()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GetParam()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.Actors;
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.lua
|
||||
{
|
||||
|
||||
[MoonSharpUserData]
|
||||
class LuaNpc
|
||||
{
|
||||
private Npc npc;
|
||||
|
||||
public LuaNpc(Npc npc)
|
||||
{
|
||||
this.npc = npc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.packets.send;
|
||||
using MoonSharp.Interpreter;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.lua
|
||||
{
|
||||
[MoonSharpUserData]
|
||||
class LuaPlayer
|
||||
{
|
||||
private Player player;
|
||||
|
||||
public LuaPlayer(Player player)
|
||||
{
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void SetMusic(ushort musicID, ushort playMode)
|
||||
{
|
||||
player.playerSession.QueuePacket(SetMusicPacket.BuildPacket(player.actorId, musicID, playMode), true, false);
|
||||
}
|
||||
|
||||
public void SetWeather(ushort weatherID)
|
||||
{
|
||||
player.playerSession.QueuePacket(SetWeatherPacket.BuildPacket(player.actorId, weatherID, 1), true, false);
|
||||
}
|
||||
|
||||
public void IssueChocobo(int appearanceId, string name)
|
||||
{
|
||||
player.IssueChocobo((byte) appearanceId, name);
|
||||
}
|
||||
|
||||
public void GetParameter(string paramName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetParameter(string paramName, object value, string uiToRefresh)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void GetAttributePoints()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetAttributePoints(int str, int vit, int dex, int inte, int min, int pie)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Logout()
|
||||
{
|
||||
player.playerSession.QueuePacket(LogoutPacket.BuildPacket(player.actorId), true, false);
|
||||
}
|
||||
|
||||
public void QuitGame()
|
||||
{
|
||||
player.playerSession.QueuePacket(QuitPacket.BuildPacket(player.actorId), true, false);
|
||||
}
|
||||
|
||||
public void RunEvent(string functionName, params object[] parameters)
|
||||
{
|
||||
List<LuaParam> lParams = LuaUtils.CreateLuaParamList(parameters);
|
||||
// player.playerSession.QueuePacket(RunEventFunctionPacket.BuildPacket(player.actorId, player.eventCurrentOwner, player.eventCurrentStarter, functionName, lParams), true, false);
|
||||
}
|
||||
|
||||
public void EndEvent()
|
||||
{
|
||||
// player.playerSession.QueuePacket(EndEventPacket.BuildPacket(player.actorId, player.eventCurrentOwner, player.eventCurrentStarter), true, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -253,6 +253,9 @@ namespace FFXIVClassic_Map_Server
|
|||
{
|
||||
List<LuaParam> luaParams = new List<LuaParam>();
|
||||
|
||||
if (fromScript == null)
|
||||
return luaParams;
|
||||
|
||||
if (fromScript.Type == DataType.Tuple)
|
||||
{
|
||||
foreach (DynValue d in fromScript.Tuple)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using FFXIVClassic_Map_Server.actors.group;
|
||||
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 PartySyncPacket
|
||||
{
|
||||
public ulong partyGroupId;
|
||||
public uint owner;
|
||||
public uint[] memberActorIds;
|
||||
|
||||
public bool invalidPacket = false;
|
||||
|
||||
public PartySyncPacket(byte[] data)
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader binReader = new BinaryReader(mem))
|
||||
{
|
||||
try
|
||||
{
|
||||
partyGroupId = binReader.ReadUInt64();
|
||||
owner = binReader.ReadUInt32();
|
||||
uint numMembers = binReader.ReadUInt32();
|
||||
memberActorIds = new uint[numMembers];
|
||||
|
||||
for (int i = 0; i < numMembers; i++)
|
||||
memberActorIds[i] = binReader.ReadUInt32();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
invalidPacket = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
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 isLogin;
|
||||
public bool invalidPacket = false;
|
||||
|
||||
public SessionBeginPacket(byte[] data)
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader binReader = new BinaryReader(mem))
|
||||
{
|
||||
try
|
||||
{
|
||||
isLogin = binReader.ReadByte() != 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
invalidPacket = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class CreateLinkshellPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1025;
|
||||
public const uint PACKET_SIZE = 0x48;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, string name, ushort crest, uint master)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
|
||||
binWriter.Write((UInt16)crest);
|
||||
binWriter.Write((UInt32)master);
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class DeleteLinkshellPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1027;
|
||||
public const uint PACKET_SIZE = 0x40;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, string name)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
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.Group
|
||||
{
|
||||
class GroupInviteResultPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1023;
|
||||
public const uint PACKET_SIZE = 0x28;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, uint groupType, uint result)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt32)groupType);
|
||||
binWriter.Write((UInt32)result);
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class LinkshellChangePacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1028;
|
||||
public const uint PACKET_SIZE = 0x48;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, string lsName)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(lsName), 0, Encoding.ASCII.GetByteCount(lsName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(lsName));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
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.Group
|
||||
{
|
||||
class LinkshellInviteCancelPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1030;
|
||||
public const uint PACKET_SIZE = 0x28;
|
||||
|
||||
public static SubPacket BuildPacket(Session session)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
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.Group
|
||||
{
|
||||
class LinkshellInvitePacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1029;
|
||||
public const uint PACKET_SIZE = 0x48;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, uint actorId, string linkshellName)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt32)actorId);
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(linkshellName), 0, Encoding.ASCII.GetByteCount(linkshellName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(linkshellName));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class LinkshellLeavePacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1031;
|
||||
public const uint PACKET_SIZE = 0x68;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, string lsName, string kickedName, bool isKicked)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt16)(isKicked ? 1 : 0));
|
||||
if (kickedName != null && isKicked)
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(kickedName), 0, Encoding.ASCII.GetByteCount(kickedName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(kickedName));
|
||||
binWriter.Seek(0x22, SeekOrigin.Begin);
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(lsName), 0, Encoding.ASCII.GetByteCount(lsName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(lsName));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class LinkshellRankChangePacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1032;
|
||||
public const uint PACKET_SIZE = 0x68;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, string name, string lsName, byte rank)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
|
||||
binWriter.Seek(0x20, SeekOrigin.Begin);
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(lsName), 0, Encoding.ASCII.GetByteCount(lsName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(lsName));
|
||||
binWriter.Seek(0x40, SeekOrigin.Begin);
|
||||
binWriter.Write((Byte)rank);
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class ModifyLinkshellPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1026;
|
||||
public const uint PACKET_SIZE = 0x60;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, ushort changeArg, string name, string newName, ushort crest, uint master)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
|
||||
binWriter.Write((UInt16)changeArg);
|
||||
switch (changeArg)
|
||||
{
|
||||
case 0:
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(newName), 0, Encoding.ASCII.GetByteCount(newName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(newName));
|
||||
break;
|
||||
case 1:
|
||||
binWriter.Write((UInt16)crest);
|
||||
break;
|
||||
case 2:
|
||||
binWriter.Write((UInt32)master);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
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.Group
|
||||
{
|
||||
class PartyInvitePacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1022;
|
||||
public const uint PACKET_SIZE = 0x48;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, string name)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt16)0);
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
public static SubPacket BuildPacket(Session session, uint actorId)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt16)1);
|
||||
binWriter.Write((UInt32)actorId);
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class PartyLeavePacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1021;
|
||||
public const uint PACKET_SIZE = 0x28;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, bool isDisband)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt16)(isDisband ? 1 : 0));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using FFXIVClassic.Common;
|
||||
using FFXIVClassic_Map_Server.Actors;
|
||||
using FFXIVClassic_Map_Server.dataobjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
|
||||
{
|
||||
class PartyModifyPacket
|
||||
{
|
||||
public const ushort OPCODE = 0x1020;
|
||||
public const uint PACKET_SIZE = 0x48;
|
||||
|
||||
public static SubPacket BuildPacket(Session session, ushort command, string name)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt16)command);
|
||||
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
public static SubPacket BuildPacket(Session session, ushort command, uint actorId)
|
||||
{
|
||||
byte[] data = new byte[PACKET_SIZE - 0x20];
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryWriter binWriter = new BinaryWriter(mem))
|
||||
{
|
||||
binWriter.Write((UInt16)(command + 2));
|
||||
binWriter.Write((UInt32)actorId);
|
||||
}
|
||||
}
|
||||
return new SubPacket(true, OPCODE, session.id, data);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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, session.id, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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, data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.receive
|
||||
{
|
||||
class GroupCreatedPacket
|
||||
{
|
||||
public ulong groupId;
|
||||
public string workString;
|
||||
|
||||
public bool invalidPacket = false;
|
||||
|
||||
public GroupCreatedPacket(byte[] data)
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader binReader = new BinaryReader(mem))
|
||||
{
|
||||
try{
|
||||
groupId = binReader.ReadUInt64();
|
||||
workString = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' });
|
||||
}
|
||||
catch (Exception){
|
||||
invalidPacket = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -3,13 +3,13 @@ using System.IO;
|
|||
|
||||
namespace FFXIVClassic_Map_Server.packets.receive
|
||||
{
|
||||
class _0x07Packet
|
||||
class ZoneInCompletePacket
|
||||
{
|
||||
public bool invalidPacket = false;
|
||||
public uint timestamp;
|
||||
public uint unknown;
|
||||
public int unknown;
|
||||
|
||||
public _0x07Packet(byte[] data)
|
||||
public ZoneInCompletePacket(byte[] data)
|
||||
{
|
||||
using (MemoryStream mem = new MemoryStream(data))
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ namespace FFXIVClassic_Map_Server.packets.receive
|
|||
{
|
||||
try{
|
||||
timestamp = binReader.ReadUInt32();
|
||||
unknown = binReader.ReadUInt32();
|
||||
unknown = binReader.ReadInt32();
|
||||
}
|
||||
catch (Exception){
|
||||
invalidPacket = true;
|
|
@ -63,6 +63,9 @@ namespace FFXIVClassic_Map_Server.packets.receive.events
|
|||
|
||||
binReader.BaseStream.Seek(0x31, SeekOrigin.Begin);
|
||||
|
||||
if (binReader.PeekChar() == 0x1)
|
||||
luaParams = new List<LuaParam>();
|
||||
else
|
||||
luaParams = LuaUtils.ReadLuaParams(binReader);
|
||||
}
|
||||
catch (Exception){
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue