mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-02 19:42:05 -04:00
Merged Ioncannon/ffxiv-classic-server into master
This commit is contained in:
commit
5ccc2435b0
@ -3,11 +3,11 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using FFXIVClassic.Common;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
|
using Ionic.Zlib;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.packets
|
namespace FFXIVClassic.Common
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct BasePacketHeader
|
public struct BasePacketHeader
|
||||||
@ -295,6 +295,41 @@ namespace FFXIVClassic_Map_Server.packets
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">Current offset in buffer.</param>
|
||||||
|
/// <param name="buffer">Incoming buffer.</param>
|
||||||
|
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
|
||||||
|
public static BasePacket CreatePacket(ref int offset, byte[] buffer, int bytesRead)
|
||||||
|
{
|
||||||
|
BasePacket newPacket = null;
|
||||||
|
|
||||||
|
//Too small to even get length
|
||||||
|
if (bytesRead <= offset)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ushort packetSize = BitConverter.ToUInt16(buffer, offset);
|
||||||
|
|
||||||
|
//Too small to whole packet
|
||||||
|
if (bytesRead < offset + packetSize)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (buffer.Length < offset + packetSize)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newPacket = new BasePacket(buffer, ref offset);
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPacket;
|
||||||
|
}
|
||||||
|
|
||||||
public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet)
|
public static unsafe void EncryptPacket(Blowfish blowfish, BasePacket packet)
|
||||||
{
|
{
|
||||||
var data = packet.data;
|
var data = packet.data;
|
||||||
@ -347,6 +382,28 @@ namespace FFXIVClassic_Map_Server.packets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static unsafe void DecompressPacket(ref BasePacket packet)
|
||||||
|
{
|
||||||
|
using (var compressedStream = new MemoryStream(packet.data))
|
||||||
|
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Decompress))
|
||||||
|
using (var resultStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
zipStream.CopyTo(resultStream);
|
||||||
|
packet.data = resultStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe void CompressPacket(ref BasePacket packet)
|
||||||
|
{
|
||||||
|
using (var compressedStream = new MemoryStream(packet.data))
|
||||||
|
using (var zipStream = new ZlibStream(compressedStream, Ionic.Zlib.CompressionMode.Compress))
|
||||||
|
using (var resultStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
zipStream.CopyTo(resultStream);
|
||||||
|
packet.data = resultStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +38,9 @@
|
|||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="DotNetZip">
|
||||||
|
<HintPath>..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
<Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
|
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -56,12 +59,14 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="BasePacket.cs" />
|
||||||
<Compile Include="Bitfield.cs" />
|
<Compile Include="Bitfield.cs" />
|
||||||
<Compile Include="Blowfish.cs" />
|
<Compile Include="Blowfish.cs" />
|
||||||
<Compile Include="EfficientHashTables.cs" />
|
<Compile Include="EfficientHashTables.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Sql.cs" />
|
<Compile Include="Sql.cs" />
|
||||||
<Compile Include="STA_INIFile.cs" />
|
<Compile Include="STA_INIFile.cs" />
|
||||||
|
<Compile Include="SubPacket.cs" />
|
||||||
<Compile Include="Utils.cs" />
|
<Compile Include="Utils.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -4,7 +4,7 @@ using FFXIVClassic.Common;
|
|||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Targets;
|
using NLog.Targets;
|
||||||
|
|
||||||
namespace FFXIVClassic_Lobby_Server.packets
|
namespace FFXIVClassic.Common
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct SubPacketHeader
|
public struct SubPacketHeader
|
||||||
@ -72,26 +72,38 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
offset += header.subpacketSize;
|
offset += header.subpacketSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data)
|
public SubPacket(ushort opcode, uint sourceId, byte[] data) : this(true, opcode, sourceId, data) { }
|
||||||
|
|
||||||
|
public SubPacket(bool isGameMessage, ushort opcode, uint sourceId, byte[] data)
|
||||||
{
|
{
|
||||||
header = new SubPacketHeader();
|
header = new SubPacketHeader();
|
||||||
gameMessage = new GameMessageHeader();
|
|
||||||
|
|
||||||
gameMessage.opcode = opcode;
|
if (isGameMessage)
|
||||||
|
{
|
||||||
|
gameMessage = new GameMessageHeader();
|
||||||
|
gameMessage.opcode = opcode;
|
||||||
|
gameMessage.timestamp = Utils.UnixTimeStampUTC();
|
||||||
|
gameMessage.unknown4 = 0x14;
|
||||||
|
gameMessage.unknown5 = 0x00;
|
||||||
|
gameMessage.unknown6 = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
header.sourceId = sourceId;
|
header.sourceId = sourceId;
|
||||||
header.targetId = targetId;
|
header.targetId = 0;
|
||||||
|
|
||||||
gameMessage.timestamp = Utils.UnixTimeStampUTC();
|
if (isGameMessage)
|
||||||
|
header.type = 0x03;
|
||||||
|
else
|
||||||
|
header.type = opcode;
|
||||||
|
|
||||||
header.type = 0x03;
|
|
||||||
header.unknown1 = 0x00;
|
header.unknown1 = 0x00;
|
||||||
gameMessage.unknown4 = 0x14;
|
|
||||||
gameMessage.unknown5 = 0x00;
|
|
||||||
gameMessage.unknown6 = 0x00;
|
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
|
||||||
header.subpacketSize = (ushort) (SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length);
|
header.subpacketSize = (ushort) (SUBPACKET_SIZE + data.Length);
|
||||||
|
|
||||||
|
if (isGameMessage)
|
||||||
|
header.subpacketSize += GAMEMESSAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubPacket(SubPacket original, uint newTargetId)
|
public SubPacket(SubPacket original, uint newTargetId)
|
||||||
@ -105,6 +117,11 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
data = original.data;
|
data = original.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetTargetId(uint target)
|
||||||
|
{
|
||||||
|
this.header.targetId = target;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] GetHeaderBytes()
|
public byte[] GetHeaderBytes()
|
||||||
{
|
{
|
||||||
var size = Marshal.SizeOf(header);
|
var size = Marshal.SizeOf(header);
|
||||||
@ -141,6 +158,41 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
return outBytes;
|
return outBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">Current offset in buffer.</param>
|
||||||
|
/// <param name="buffer">Incoming buffer.</param>
|
||||||
|
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
|
||||||
|
public static SubPacket CreatePacket(ref int offset, byte[] buffer, int bytesRead)
|
||||||
|
{
|
||||||
|
SubPacket newPacket = null;
|
||||||
|
|
||||||
|
//Too small to even get length
|
||||||
|
if (bytesRead <= offset)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ushort packetSize = BitConverter.ToUInt16(buffer, offset);
|
||||||
|
|
||||||
|
//Too small to whole packet
|
||||||
|
if (bytesRead < offset + packetSize)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (buffer.Length < offset + packetSize)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newPacket = new SubPacket(buffer, ref offset);
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPacket;
|
||||||
|
}
|
||||||
|
|
||||||
public void DebugPrintSubPacket()
|
public void DebugPrintSubPacket()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -157,6 +209,9 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
|
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE + GAMEMESSAGE_SIZE),
|
||||||
ConsoleOutputColor.DarkMagenta);
|
ConsoleOutputColor.DarkMagenta);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
logger.ColorDebug(Utils.ByteArrayToHex(data, SUBPACKET_SIZE),
|
||||||
|
ConsoleOutputColor.DarkMagenta);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Microsoft.Net.Compilers" version="2.0.0-beta3" targetFramework="net45" developmentDependency="true" />
|
<package id="DotNetZip" version="1.10.1" targetFramework="net45" />
|
||||||
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
|
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
|
||||||
<package id="NLog" version="4.3.5" targetFramework="net45" />
|
<package id="NLog" version="4.3.5" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using FFXIVClassic_Lobby_Server.packets;
|
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using Cyotek.Collections.Generic;
|
using Cyotek.Collections.Generic;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace FFXIVClassic_Lobby_Server
|
namespace FFXIVClassic_Lobby_Server
|
||||||
{
|
{
|
||||||
@ -23,7 +25,7 @@ namespace FFXIVClassic_Lobby_Server
|
|||||||
if (!File.Exists("./lobby_config.ini"))
|
if (!File.Exists("./lobby_config.ini"))
|
||||||
{
|
{
|
||||||
Program.Log.Error("FILE NOT FOUND!");
|
Program.Log.Error("FILE NOT FOUND!");
|
||||||
return false;
|
Program.Log.Error("Loading defaults...");
|
||||||
}
|
}
|
||||||
|
|
||||||
INIFile configIni = new INIFile("./lobby_config.ini");
|
INIFile configIni = new INIFile("./lobby_config.ini");
|
||||||
@ -40,5 +42,49 @@ namespace FFXIVClassic_Lobby_Server
|
|||||||
|
|
||||||
return true;
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<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="..\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') AND '$(OS)' == 'Windows_NT'" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
@ -91,7 +91,6 @@
|
|||||||
<Compile Include="Database.cs" />
|
<Compile Include="Database.cs" />
|
||||||
<Compile Include="dataobjects\World.cs" />
|
<Compile Include="dataobjects\World.cs" />
|
||||||
<Compile Include="PacketProcessor.cs" />
|
<Compile Include="PacketProcessor.cs" />
|
||||||
<Compile Include="packets\BasePacket.cs" />
|
|
||||||
<Compile Include="packets\receive\CharacterModifyPacket.cs" />
|
<Compile Include="packets\receive\CharacterModifyPacket.cs" />
|
||||||
<Compile Include="packets\receive\SecurityHandshakePacket.cs" />
|
<Compile Include="packets\receive\SecurityHandshakePacket.cs" />
|
||||||
<Compile Include="packets\receive\SelectCharacterPacket.cs" />
|
<Compile Include="packets\receive\SelectCharacterPacket.cs" />
|
||||||
@ -101,7 +100,6 @@
|
|||||||
<Compile Include="packets\send\ErrorPacket.cs" />
|
<Compile Include="packets\send\ErrorPacket.cs" />
|
||||||
<Compile Include="packets\HardCoded_Packets.cs" />
|
<Compile Include="packets\HardCoded_Packets.cs" />
|
||||||
<Compile Include="packets\send\SelectCharacterConfirmPacket.cs" />
|
<Compile Include="packets\send\SelectCharacterConfirmPacket.cs" />
|
||||||
<Compile Include="packets\SubPacket.cs" />
|
|
||||||
<Compile Include="packets\send\CharacterListPacket.cs" />
|
<Compile Include="packets\send\CharacterListPacket.cs" />
|
||||||
<Compile Include="packets\send\ImportListPacket.cs" />
|
<Compile Include="packets\send\ImportListPacket.cs" />
|
||||||
<Compile Include="packets\send\AccountListPacket.cs" />
|
<Compile Include="packets\send\AccountListPacket.cs" />
|
||||||
@ -135,7 +133,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<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>
|
</PropertyGroup>
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
@ -38,13 +38,13 @@
|
|||||||
<target xsi:type="ColoredConsole" name="packets"
|
<target xsi:type="ColoredConsole" name="packets"
|
||||||
layout="${message}">
|
layout="${message}">
|
||||||
<highlight-row
|
<highlight-row
|
||||||
condition="equals('${logger}', 'FFXIVClassic_Lobby_Server.packets.BasePacket') and equals('${event-context:item=color}', '6')"
|
condition="equals('${logger}', 'FFXIVClassic.Common.BasePacket') and equals('${event-context:item=color}', '6')"
|
||||||
backgroundColor="DarkYellow" foregroundColor="NoChange" />
|
backgroundColor="DarkYellow" foregroundColor="NoChange" />
|
||||||
<highlight-row
|
<highlight-row
|
||||||
condition="equals('${logger}', 'FFXIVClassic_Lobby_Server.packets.SubPacket') and equals('${event-context:item=color}', '4')"
|
condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '4')"
|
||||||
backgroundColor="DarkRed" foregroundColor="NoChange" />
|
backgroundColor="DarkRed" foregroundColor="NoChange" />
|
||||||
<highlight-row
|
<highlight-row
|
||||||
condition="equals('${logger}', 'FFXIVClassic_Lobby_Server.packets.SubPacket') and equals('${event-context:item=color}', '5')"
|
condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '5')"
|
||||||
backgroundColor="DarkMagenta" foregroundColor="NoChange" />
|
backgroundColor="DarkMagenta" foregroundColor="NoChange" />
|
||||||
</target>
|
</target>
|
||||||
</targets>
|
</targets>
|
||||||
|
@ -90,14 +90,15 @@ namespace FFXIVClassic_Lobby_Server
|
|||||||
|
|
||||||
if (userId == 0)
|
if (userId == 0)
|
||||||
{
|
{
|
||||||
ErrorPacket errorPacket = new ErrorPacket(sessionPacket.sequence, 0, 0, 13001, "Your session has expired, please login again.");
|
ErrorPacket errorPacket = new ErrorPacket(sessionPacket.sequence, 0, 0, 13001, "Your session has expired, please login again.");
|
||||||
SubPacket subpacket = errorPacket.BuildPacket();
|
SubPacket subpacket = errorPacket.BuildPacket();
|
||||||
BasePacket errorBasePacket = BasePacket.CreatePacket(subpacket, true, false);
|
subpacket.SetTargetId(0xe0006868);
|
||||||
BasePacket.EncryptPacket(client.blowfish, errorBasePacket);
|
BasePacket errorBasePacket = BasePacket.CreatePacket(subpacket, true, false);
|
||||||
client.QueuePacket(errorBasePacket);
|
BasePacket.EncryptPacket(client.blowfish, errorBasePacket);
|
||||||
|
client.QueuePacket(errorBasePacket);
|
||||||
|
|
||||||
Program.Log.Info("Invalid session, kicking...");
|
Program.Log.Info("Invalid session, kicking...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Program.Log.Info("USER ID: {0}", userId);
|
Program.Log.Info("USER ID: {0}", userId);
|
||||||
|
@ -20,13 +20,16 @@ namespace FFXIVClassic_Lobby_Server
|
|||||||
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
|
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
|
||||||
Debug.Listeners.Add(myWriter);
|
Debug.Listeners.Add(myWriter);
|
||||||
#endif
|
#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;
|
bool startServer = true;
|
||||||
|
|
||||||
//Load Config
|
//Load Config
|
||||||
if (!ConfigConstants.Load())
|
ConfigConstants.Load();
|
||||||
startServer = false;
|
ConfigConstants.ApplyLaunchArgs(args);
|
||||||
|
|
||||||
//Test DB Connection
|
//Test DB Connection
|
||||||
Program.Log.Info("Testing DB connection to \"{0}\"... ", ConfigConstants.DATABASE_HOST);
|
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;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using FFXIVClassic_Lobby_Server.packets;
|
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -60,7 +61,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
accountCount = 0;
|
accountCount = 0;
|
||||||
}
|
}
|
||||||
@ -87,7 +89,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using FFXIVClassic.Common;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -86,7 +87,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
characterCount = 0;
|
characterCount = 0;
|
||||||
}
|
}
|
||||||
@ -132,7 +134,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
characterCount = 0;
|
characterCount = 0;
|
||||||
}
|
}
|
||||||
@ -144,7 +147,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using FFXIVClassic.Common;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -37,7 +38,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
return subpacket;
|
return subpacket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using FFXIVClassic.Common;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -63,7 +64,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
namesCount = 0;
|
namesCount = 0;
|
||||||
}
|
}
|
||||||
@ -90,7 +92,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using FFXIVClassic.Common;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -64,7 +65,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
retainerCount = 0;
|
retainerCount = 0;
|
||||||
}
|
}
|
||||||
@ -91,7 +93,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using FFXIVClassic.Common;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -48,7 +49,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
data = memStream.GetBuffer();
|
data = memStream.GetBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
|
|
||||||
return subPackets;
|
return subPackets;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using FFXIVClassic_Lobby_Server.dataobjects;
|
using FFXIVClassic.Common;
|
||||||
|
using FFXIVClassic_Lobby_Server.dataobjects;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -62,7 +63,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
serverCount = 0;
|
serverCount = 0;
|
||||||
}
|
}
|
||||||
@ -89,7 +91,8 @@ namespace FFXIVClassic_Lobby_Server.packets
|
|||||||
byte[] data = memStream.GetBuffer();
|
byte[] data = memStream.GetBuffer();
|
||||||
binWriter.Dispose();
|
binWriter.Dispose();
|
||||||
memStream.Dispose();
|
memStream.Dispose();
|
||||||
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, 0xe0006868, data);
|
SubPacket subpacket = new SubPacket(OPCODE, 0xe0006868, data);
|
||||||
|
subpacket.SetTargetId(0xe0006868);
|
||||||
subPackets.Add(subpacket);
|
subPackets.Add(subpacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,72 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
using FFXIVClassic_Map_Server;
|
|
||||||
using FFXIVClassic_Map_Server.packets.send;
|
using FFXIVClassic_Map_Server.packets.send;
|
||||||
using FFXIVClassic_Map_Server.dataobjects.chara;
|
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.actors.chara.player;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
using FFXIVClassic_Map_Server.Properties;
|
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server
|
namespace FFXIVClassic_Map_Server
|
||||||
{
|
{
|
||||||
class CommandProcessor
|
class CommandProcessor
|
||||||
{
|
{
|
||||||
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList;
|
private static Dictionary<uint, ItemData> gamedataItems = Server.GetGamedataItems();
|
||||||
private static Dictionary<uint, Item> gamedataItems = Server.GetGamedataItems();
|
|
||||||
|
|
||||||
// For the moment, this is the only predefined item
|
|
||||||
// TODO: make a list/enum in the future so that items can be given by name, instead of by id
|
|
||||||
const UInt32 ITEM_GIL = 1000001;
|
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>
|
/// <summary>
|
||||||
/// We only use the default options for SendMessagePacket.
|
/// We only use the default options for SendMessagePacket.
|
||||||
/// May as well make it less unwieldly to view
|
/// May as well make it less unwieldly to view
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="client"></param>
|
/// <param name="client"></param>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
private void SendMessage(ConnectedPlayer client, String message)
|
private void SendMessage(Session session, String message)
|
||||||
{
|
{
|
||||||
if (client != null)
|
if (session != null)
|
||||||
client.GetActor().QueuePacket(SendMessagePacket.BuildPacket(client.actorID, client.actorID, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message));
|
session.GetActor().QueuePacket(SendMessagePacket.BuildPacket(session.id, SendMessagePacket.MESSAGE_TYPE_GENERAL_INFO, "", message));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool DoCommand(string input, ConnectedPlayer client)
|
internal bool DoCommand(string input, Session session)
|
||||||
{
|
{
|
||||||
if (!input.Any() || input.Equals(""))
|
if (!input.Any() || input.Equals(""))
|
||||||
return false;
|
return false;
|
||||||
@ -81,14 +45,16 @@ namespace FFXIVClassic_Map_Server
|
|||||||
)
|
)
|
||||||
.SelectMany(str => str).ToArray();
|
.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];
|
var cmd = split[0];
|
||||||
|
|
||||||
if (cmd.Any())
|
if (cmd.Any())
|
||||||
{
|
{
|
||||||
// if client isnt null, take player to be the player actor
|
// if client isnt null, take player to be the player actor
|
||||||
var player = client?.GetActor();
|
Player player = null;
|
||||||
|
if (session != null)
|
||||||
|
player = session.GetActor();
|
||||||
|
|
||||||
if (cmd.Equals("help"))
|
if (cmd.Equals("help"))
|
||||||
{
|
{
|
||||||
@ -125,11 +91,11 @@ namespace FFXIVClassic_Map_Server
|
|||||||
if (split[0].Equals("reloaditems"))
|
if (split[0].Equals("reloaditems"))
|
||||||
{
|
{
|
||||||
Program.Log.Info(String.Format("Got request to reload item gamedata"));
|
Program.Log.Info(String.Format("Got request to reload item gamedata"));
|
||||||
SendMessage(client, "Reloading Item Gamedata...");
|
SendMessage(session, "Reloading Item Gamedata...");
|
||||||
gamedataItems.Clear();
|
gamedataItems.Clear();
|
||||||
gamedataItems = Database.GetItemGamedata();
|
gamedataItems = Database.GetItemGamedata();
|
||||||
Program.Log.Info(String.Format("Loaded {0} items.", gamedataItems.Count));
|
Program.Log.Info(String.Format("Loaded {0} items.", gamedataItems.Count));
|
||||||
SendMessage(client, String.Format("Loaded {0} items.", gamedataItems.Count));
|
SendMessage(session, String.Format("Loaded {0} items.", gamedataItems.Count));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -139,7 +105,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
if (split.Length == 4)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -150,7 +116,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
if (split.Length == 4)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using MoonSharp.Interpreter.Interop;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server
|
namespace FFXIVClassic_Map_Server
|
||||||
{
|
{
|
||||||
@ -8,9 +13,9 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
public static String OPTIONS_BINDIP;
|
public static String OPTIONS_BINDIP;
|
||||||
public static String OPTIONS_PORT;
|
public static String OPTIONS_PORT;
|
||||||
public static bool OPTIONS_TIMESTAMP = false;
|
public static bool OPTIONS_TIMESTAMP = false;
|
||||||
|
|
||||||
public static uint DATABASE_WORLDID;
|
public static uint DATABASE_WORLDID;
|
||||||
public static String DATABASE_HOST;
|
public static String DATABASE_HOST;
|
||||||
public static String DATABASE_PORT;
|
public static String DATABASE_PORT;
|
||||||
public static String DATABASE_NAME;
|
public static String DATABASE_NAME;
|
||||||
@ -24,13 +29,13 @@ namespace FFXIVClassic_Map_Server
|
|||||||
if (!File.Exists("./map_config.ini"))
|
if (!File.Exists("./map_config.ini"))
|
||||||
{
|
{
|
||||||
Program.Log.Error("FILE NOT FOUND");
|
Program.Log.Error("FILE NOT FOUND");
|
||||||
return false;
|
Program.Log.Error("Loading defaults... ");
|
||||||
}
|
}
|
||||||
|
|
||||||
INIFile configIni = new INIFile("./map_config.ini");
|
INIFile configIni = new INIFile("./map_config.ini");
|
||||||
|
|
||||||
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1");
|
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1");
|
||||||
ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "54992");
|
ConfigConstants.OPTIONS_PORT = configIni.GetValue("General", "server_port", "1989");
|
||||||
ConfigConstants.OPTIONS_TIMESTAMP = configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true");
|
ConfigConstants.OPTIONS_TIMESTAMP = configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true");
|
||||||
|
|
||||||
ConfigConstants.DATABASE_WORLDID = UInt32.Parse(configIni.GetValue("Database", "worldid", "0"));
|
ConfigConstants.DATABASE_WORLDID = UInt32.Parse(configIni.GetValue("Database", "worldid", "0"));
|
||||||
@ -42,5 +47,50 @@ namespace FFXIVClassic_Map_Server
|
|||||||
|
|
||||||
return true;
|
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 System.Linq;
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.utils;
|
using FFXIVClassic_Map_Server.utils;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic_Map_Server.packets.send.player;
|
using FFXIVClassic_Map_Server.packets.send.player;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
@ -48,29 +48,6 @@ namespace FFXIVClassic_Map_Server
|
|||||||
return id;
|
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()
|
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)))
|
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)))
|
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
|
try
|
||||||
{
|
{
|
||||||
@ -108,11 +85,12 @@ namespace FFXIVClassic_Map_Server
|
|||||||
SELECT
|
SELECT
|
||||||
*
|
*
|
||||||
FROM gamedata_items
|
FROM gamedata_items
|
||||||
LEFT JOIN gamedata_items_equipment ON gamedata_items.catalogID = gamedata_items_equipment.catalogID
|
LEFT JOIN gamedata_items_equipment ON gamedata_items.catalogID = gamedata_items_equipment.catalogID
|
||||||
LEFT JOIN gamedata_items_accessory ON gamedata_items.catalogID = gamedata_items_accessory.catalogID
|
LEFT JOIN gamedata_items_accessory ON gamedata_items.catalogID = gamedata_items_accessory.catalogID
|
||||||
LEFT JOIN gamedata_items_armor ON gamedata_items.catalogID = gamedata_items_armor.catalogID
|
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_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 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);
|
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||||
@ -122,16 +100,16 @@ namespace FFXIVClassic_Map_Server
|
|||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
uint id = reader.GetUInt32("catalogID");
|
uint id = reader.GetUInt32("catalogID");
|
||||||
Item item = null;
|
ItemData item = null;
|
||||||
|
|
||||||
if (Item.IsWeapon(id))
|
if (ItemData.IsWeapon(id))
|
||||||
item = new WeaponItem(reader);
|
item = new WeaponItem(reader);
|
||||||
else if (Item.IsArmor(id))
|
else if (ItemData.IsArmor(id))
|
||||||
item = new ArmorItem(reader);
|
item = new ArmorItem(reader);
|
||||||
else if (Item.IsAccessory(id))
|
else if (ItemData.IsAccessory(id))
|
||||||
item = new AccessoryItem(reader);
|
item = new AccessoryItem(reader);
|
||||||
else
|
else
|
||||||
item = new Item(reader);
|
item = new ItemData(reader);
|
||||||
|
|
||||||
gamedataItems.Add(item.catalogID, item);
|
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)
|
public static void SavePlayerAppearance(Player player)
|
||||||
{
|
{
|
||||||
string query;
|
string query;
|
||||||
@ -259,7 +278,11 @@ namespace FFXIVClassic_Map_Server
|
|||||||
positionY = @y,
|
positionY = @y,
|
||||||
positionZ = @z,
|
positionZ = @z,
|
||||||
rotation = @rot,
|
rotation = @rot,
|
||||||
currentZoneId = @zoneId
|
destinationZoneId = @destZone,
|
||||||
|
destinationSpawnType = @destSpawn,
|
||||||
|
currentZoneId = @zoneId,
|
||||||
|
currentPrivateArea = @privateArea,
|
||||||
|
currentPrivateAreaType = @privateAreaType
|
||||||
WHERE id = @charaId
|
WHERE id = @charaId
|
||||||
";
|
";
|
||||||
|
|
||||||
@ -270,6 +293,10 @@ namespace FFXIVClassic_Map_Server
|
|||||||
cmd.Parameters.AddWithValue("@z", player.positionZ);
|
cmd.Parameters.AddWithValue("@z", player.positionZ);
|
||||||
cmd.Parameters.AddWithValue("@rot", player.rotation);
|
cmd.Parameters.AddWithValue("@rot", player.rotation);
|
||||||
cmd.Parameters.AddWithValue("@zoneId", player.zoneId);
|
cmd.Parameters.AddWithValue("@zoneId", player.zoneId);
|
||||||
|
cmd.Parameters.AddWithValue("@privateArea", player.privateArea);
|
||||||
|
cmd.Parameters.AddWithValue("@privateAreaType", player.privateAreaType);
|
||||||
|
cmd.Parameters.AddWithValue("@destZone", player.destinationZone);
|
||||||
|
cmd.Parameters.AddWithValue("@destSpawn", player.destinationSpawnType);
|
||||||
|
|
||||||
cmd.ExecuteNonQuery();
|
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)
|
public static void SaveQuest(Player player, Quest quest)
|
||||||
{
|
{
|
||||||
int slot = player.GetQuestSlot(quest.actorId);
|
int slot = player.GetQuestSlot(quest.actorId);
|
||||||
@ -343,17 +406,18 @@ namespace FFXIVClassic_Map_Server
|
|||||||
|
|
||||||
query = @"
|
query = @"
|
||||||
INSERT INTO characters_quest_scenario
|
INSERT INTO characters_quest_scenario
|
||||||
(characterId, slot, questId, questData, questFlags)
|
(characterId, slot, questId, currentPhase, questData, questFlags)
|
||||||
VALUES
|
VALUES
|
||||||
(@charaId, @slot, @questId, @questData, @questFlags)
|
(@charaId, @slot, @questId, @phase, @questData, @questFlags)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
questData = @questData, questFlags = @questFlags
|
questId = @questId, currentPhase = @phase, questData = @questData, questFlags = @questFlags
|
||||||
";
|
";
|
||||||
|
|
||||||
cmd = new MySqlCommand(query, conn);
|
cmd = new MySqlCommand(query, conn);
|
||||||
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
cmd.Parameters.AddWithValue("@charaId", player.actorId);
|
||||||
cmd.Parameters.AddWithValue("@slot", slot);
|
cmd.Parameters.AddWithValue("@slot", slot);
|
||||||
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.actorId);
|
cmd.Parameters.AddWithValue("@questId", 0xFFFFF & quest.actorId);
|
||||||
|
cmd.Parameters.AddWithValue("@phase", quest.GetPhase());
|
||||||
cmd.Parameters.AddWithValue("@questData", quest.GetSerializedQuestData());
|
cmd.Parameters.AddWithValue("@questData", quest.GetSerializedQuestData());
|
||||||
cmd.Parameters.AddWithValue("@questFlags", quest.GetQuestFlags());
|
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)
|
public static void LoadPlayerCharacter(Player player)
|
||||||
{
|
{
|
||||||
string query;
|
string query;
|
||||||
@ -403,7 +670,13 @@ namespace FFXIVClassic_Map_Server
|
|||||||
tribe,
|
tribe,
|
||||||
restBonus,
|
restBonus,
|
||||||
achievementPoints,
|
achievementPoints,
|
||||||
playTime
|
playTime,
|
||||||
|
destinationZoneId,
|
||||||
|
destinationSpawnType,
|
||||||
|
currentPrivateArea,
|
||||||
|
currentPrivateAreaType,
|
||||||
|
homepoint,
|
||||||
|
homepointInn
|
||||||
FROM characters WHERE id = @charId";
|
FROM characters WHERE id = @charId";
|
||||||
|
|
||||||
cmd = new MySqlCommand(query, conn);
|
cmd = new MySqlCommand(query, conn);
|
||||||
@ -421,7 +694,6 @@ namespace FFXIVClassic_Map_Server
|
|||||||
player.currentMainState = reader.GetUInt16(5);
|
player.currentMainState = reader.GetUInt16(5);
|
||||||
player.zoneId = reader.GetUInt32(6);
|
player.zoneId = reader.GetUInt32(6);
|
||||||
player.isZoning = true;
|
player.isZoning = true;
|
||||||
player.zone = Server.GetWorldManager().GetZone(player.zoneId);
|
|
||||||
player.gcCurrent = reader.GetByte(7);
|
player.gcCurrent = reader.GetByte(7);
|
||||||
player.gcRankLimsa = reader.GetByte(8);
|
player.gcRankLimsa = reader.GetByte(8);
|
||||||
player.gcRankGridania = reader.GetByte(9);
|
player.gcRankGridania = reader.GetByte(9);
|
||||||
@ -435,6 +707,22 @@ namespace FFXIVClassic_Map_Server
|
|||||||
player.playerWork.restBonusExpRate = reader.GetInt32(17);
|
player.playerWork.restBonusExpRate = reader.GetInt32(17);
|
||||||
player.achievementPoints = reader.GetUInt32(18);
|
player.achievementPoints = reader.GetUInt32(18);
|
||||||
player.playTime = reader.GetUInt32(19);
|
player.playTime = reader.GetUInt32(19);
|
||||||
|
player.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,
|
slot,
|
||||||
questId,
|
questId,
|
||||||
questData,
|
questData,
|
||||||
questFlags
|
questFlags,
|
||||||
|
currentPhase
|
||||||
FROM characters_quest_scenario WHERE characterId = @charId";
|
FROM characters_quest_scenario WHERE characterId = @charId";
|
||||||
|
|
||||||
cmd = new MySqlCommand(query, conn);
|
cmd = new MySqlCommand(query, conn);
|
||||||
@ -703,6 +992,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
player.playerWork.questScenario[index] = 0xA0F00000 | reader.GetUInt32(1);
|
player.playerWork.questScenario[index] = 0xA0F00000 | reader.GetUInt32(1);
|
||||||
string questData = null;
|
string questData = null;
|
||||||
uint questFlags = 0;
|
uint questFlags = 0;
|
||||||
|
uint currentPhase = 0;
|
||||||
|
|
||||||
if (!reader.IsDBNull(2))
|
if (!reader.IsDBNull(2))
|
||||||
questData = reader.GetString(2);
|
questData = reader.GetString(2);
|
||||||
@ -714,8 +1004,11 @@ namespace FFXIVClassic_Map_Server
|
|||||||
else
|
else
|
||||||
questFlags = 0;
|
questFlags = 0;
|
||||||
|
|
||||||
|
if (!reader.IsDBNull(4))
|
||||||
|
currentPhase = reader.GetUInt32(4);
|
||||||
|
|
||||||
string questName = Server.GetStaticActors(player.playerWork.questScenario[index]).actorName;
|
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);
|
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)
|
public static bool SaveSupportTicket(GMSupportTicketPacket gmTicket, string playerName)
|
||||||
{
|
{
|
||||||
@ -1556,4 +1925,5 @@ namespace FFXIVClassic_Map_Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Cyotek.Collections.Generic.CircularBuffer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58daa28b0b2de221, processorArchitecture=MSIL">
|
<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>
|
<HintPath>..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
|
||||||
@ -73,6 +76,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="actors\area\PrivateArea.cs" />
|
<Compile Include="actors\area\PrivateArea.cs" />
|
||||||
|
<Compile Include="actors\area\PrivateAreaContent.cs" />
|
||||||
<Compile Include="actors\area\SpawnLocation.cs" />
|
<Compile Include="actors\area\SpawnLocation.cs" />
|
||||||
<Compile Include="actors\area\Zone.cs" />
|
<Compile Include="actors\area\Zone.cs" />
|
||||||
<Compile Include="actors\chara\npc\ActorClass.cs" />
|
<Compile Include="actors\chara\npc\ActorClass.cs" />
|
||||||
@ -83,17 +87,28 @@
|
|||||||
<Compile Include="actors\chara\Work.cs" />
|
<Compile Include="actors\chara\Work.cs" />
|
||||||
<Compile Include="actors\debug\Debug.cs" />
|
<Compile Include="actors\debug\Debug.cs" />
|
||||||
<Compile Include="actors\director\Director.cs" />
|
<Compile Include="actors\director\Director.cs" />
|
||||||
<Compile Include="actors\director\OpeningDirector.cs" />
|
<Compile Include="actors\director\GuildleveDirector.cs" />
|
||||||
<Compile Include="actors\director\quest\QuestDirectorMan0g001.cs" />
|
<Compile Include="actors\director\Work\GuildleveWork.cs" />
|
||||||
<Compile Include="actors\director\quest\QuestDirectorMan0l001.cs" />
|
|
||||||
<Compile Include="actors\director\quest\QuestDirectorMan0u001.cs" />
|
|
||||||
<Compile Include="actors\director\WeatherDirector.cs" />
|
|
||||||
<Compile Include="actors\EventList.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\judge\Judge.cs" />
|
||||||
<Compile Include="actors\quest\Quest.cs" />
|
<Compile Include="actors\quest\Quest.cs" />
|
||||||
<Compile Include="actors\StaticActors.cs" />
|
<Compile Include="actors\StaticActors.cs" />
|
||||||
<Compile Include="actors\world\WorldMaster.cs" />
|
<Compile Include="actors\world\WorldMaster.cs" />
|
||||||
<Compile Include="ClientConnection.cs" />
|
<Compile Include="dataobjects\GuildleveData.cs" />
|
||||||
|
<Compile Include="dataobjects\ZoneConnection.cs" />
|
||||||
<Compile Include="CommandProcessor.cs" />
|
<Compile Include="CommandProcessor.cs" />
|
||||||
<Compile Include="ConfigConstants.cs" />
|
<Compile Include="ConfigConstants.cs" />
|
||||||
<Compile Include="Database.cs" />
|
<Compile Include="Database.cs" />
|
||||||
@ -110,24 +125,21 @@
|
|||||||
<Compile Include="actors\chara\CharaWork.cs" />
|
<Compile Include="actors\chara\CharaWork.cs" />
|
||||||
<Compile Include="actors\chara\ParameterSave.cs" />
|
<Compile Include="actors\chara\ParameterSave.cs" />
|
||||||
<Compile Include="actors\chara\player\PlayerWork.cs" />
|
<Compile Include="actors\chara\player\PlayerWork.cs" />
|
||||||
<Compile Include="dataobjects\DBWorld.cs" />
|
|
||||||
<Compile Include="dataobjects\InventoryItem.cs" />
|
<Compile Include="dataobjects\InventoryItem.cs" />
|
||||||
<Compile Include="dataobjects\ConnectedPlayer.cs" />
|
<Compile Include="dataobjects\Session.cs" />
|
||||||
<Compile Include="dataobjects\Item.cs" />
|
<Compile Include="dataobjects\ItemData.cs" />
|
||||||
<Compile Include="dataobjects\RecruitmentDetails.cs" />
|
<Compile Include="dataobjects\RecruitmentDetails.cs" />
|
||||||
<Compile Include="dataobjects\SeamlessBoundry.cs" />
|
<Compile Include="dataobjects\SeamlessBoundry.cs" />
|
||||||
<Compile Include="dataobjects\SearchEntry.cs" />
|
<Compile Include="dataobjects\SearchEntry.cs" />
|
||||||
<Compile Include="lua\LuaEngine.cs" />
|
<Compile Include="lua\LuaEngine.cs" />
|
||||||
<Compile Include="lua\LuaEvent.cs" />
|
|
||||||
<Compile Include="lua\LuaParam.cs" />
|
<Compile Include="lua\LuaParam.cs" />
|
||||||
<Compile Include="lua\LuaNpc.cs" />
|
|
||||||
<Compile Include="lua\LuaPlayer.cs" />
|
|
||||||
<Compile Include="lua\LuaScript.cs" />
|
<Compile Include="lua\LuaScript.cs" />
|
||||||
|
<Compile Include="lua\LuaUtils.cs" />
|
||||||
<Compile Include="PacketProcessor.cs" />
|
<Compile Include="PacketProcessor.cs" />
|
||||||
<Compile Include="packets\BasePacket.cs" />
|
|
||||||
<Compile Include="packets\receive\ChatMessagePacket.cs" />
|
<Compile Include="packets\receive\ChatMessagePacket.cs" />
|
||||||
<Compile Include="packets\receive\events\EventUpdatePacket.cs" />
|
<Compile Include="packets\receive\events\EventUpdatePacket.cs" />
|
||||||
<Compile Include="packets\receive\events\EventStartPacket.cs" />
|
<Compile Include="packets\receive\events\EventStartPacket.cs" />
|
||||||
|
<Compile Include="packets\receive\GroupCreatedPacket.cs" />
|
||||||
<Compile Include="packets\receive\HandshakePacket.cs" />
|
<Compile Include="packets\receive\HandshakePacket.cs" />
|
||||||
<Compile Include="packets\receive\LangaugeCodePacket.cs" />
|
<Compile Include="packets\receive\LangaugeCodePacket.cs" />
|
||||||
<Compile Include="packets\receive\ParameterDataRequestPacket.cs" />
|
<Compile Include="packets\receive\ParameterDataRequestPacket.cs" />
|
||||||
@ -143,63 +155,74 @@
|
|||||||
<Compile Include="packets\receive\supportdesk\GMSupportTicketPacket.cs" />
|
<Compile Include="packets\receive\supportdesk\GMSupportTicketPacket.cs" />
|
||||||
<Compile Include="packets\receive\supportdesk\GMTicketIssuesRequestPacket.cs" />
|
<Compile Include="packets\receive\supportdesk\GMTicketIssuesRequestPacket.cs" />
|
||||||
<Compile Include="packets\receive\_0x02ReceivePacket.cs" />
|
<Compile Include="packets\receive\_0x02ReceivePacket.cs" />
|
||||||
<Compile Include="packets\receive\_0x07Packet.cs" />
|
<Compile Include="packets\receive\ZoneInCompletePacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\ActorDoEmotePacket.cs" />
|
<Compile Include="packets\send\actor\ActorDoEmotePacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\ActorInstantiatePacket.cs" />
|
<Compile Include="packets\send\actor\ActorInstantiatePacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\ActorSpecialGraphicPacket.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\BattleAction.cs" />
|
<Compile Include="packets\send\actor\battle\BattleActionX00Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\battle\BattleActionX00Packet.cs" />
|
<Compile Include="packets\send\actor\battle\BattleActionX18Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\battle\BattleActionX18Packet.cs" />
|
<Compile Include="packets\send\actor\battle\BattleActionX10Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\battle\BattleActionX10Packet.cs" />
|
<Compile Include="packets\send\actor\DeleteAllActorsPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\DeleteAllActorsPacket.cs" />
|
<Compile Include="packets\send\actor\events\SetEventStatus.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetEventStatus.cs" />
|
<Compile Include="packets\send\actor\events\SetNoticeEventCondition.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetNoticeEventCondition.cs" />
|
<Compile Include="packets\send\actor\events\SetPushEventConditionWithTriggerBox.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetPushEventConditionWithTriggerBox.cs" />
|
<Compile Include="packets\send\actor\events\SetPushEventConditionWithFan.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetPushEventConditionWithFan.cs" />
|
<Compile Include="packets\send\actor\events\SetEmoteEventCondition.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetEmoteEventCondition.cs" />
|
<Compile Include="packets\send\actor\events\SetTalkEventCondition.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetTalkEventCondition.cs" />
|
<Compile Include="packets\send\actor\events\SetPushEventConditionWithCircle.cs" />
|
||||||
<Compile Include="packets\send\Actor\events\SetPushEventConditionWithCircle.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryRemoveX01Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX01Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryRemoveX08Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX08Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryRemoveX16Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX16Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryRemoveX32Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX32Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryRemoveX64Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryRemoveX64Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\EquipmentListX64Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX64Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\EquipmentListX32Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX32Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\EquipmentListX16Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX16Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryListX01Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryListX01Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryListX08Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryListX08Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryListX16Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryListX16Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryListX64Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryListX64Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryListX32Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryListX32Packet.cs" />
|
<Compile Include="packets\send\actor\PlayAnimationOnActorPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\_0x132Packet.cs" />
|
<Compile Include="packets\send\actor\PlayBGAnimation.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorIsZoningPacket.cs" />
|
<Compile Include="packets\send\actor\_0x132Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\battle\BattleActionX01Packet.cs" />
|
<Compile Include="packets\send\actor\SetActorIsZoningPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX01Packet.cs" />
|
<Compile Include="packets\send\actor\battle\BattleActionX01Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryBeginChangePacket.cs" />
|
<Compile Include="packets\send\actor\inventory\EquipmentListX01Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryEndChangePacket.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryBeginChangePacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryItemEndPacket.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryEndChangePacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventoryItemPacket.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryItemEndPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventorySetBeginPacket.cs" />
|
<Compile Include="packets\send\actor\inventory\InventoryItemPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\InventorySetEndPacket.cs" />
|
<Compile Include="packets\send\actor\inventory\InventorySetBeginPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\inventory\EquipmentListX08Packet.cs" />
|
<Compile Include="packets\send\actor\inventory\InventorySetEndPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\RemoveActorPacket.cs" />
|
<Compile Include="packets\send\actor\inventory\EquipmentListX08Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorIconPacket.cs" />
|
<Compile Include="packets\send\actor\RemoveActorPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorIdleAnimationPacket.cs" />
|
<Compile Include="packets\send\actor\SetActorIconPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorStatusPacket.cs" />
|
<Compile Include="packets\send\actor\SetActorSubStatPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\_0xFPacket.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\EndEventPacket.cs" />
|
||||||
<Compile Include="packets\send\events\KickEventPacket.cs" />
|
<Compile Include="packets\send\events\KickEventPacket.cs" />
|
||||||
<Compile Include="packets\send\events\RunEventFunctionPacket.cs" />
|
<Compile Include="packets\send\events\RunEventFunctionPacket.cs" />
|
||||||
<Compile Include="packets\send\GameMessagePacket.cs" />
|
<Compile Include="packets\send\GameMessagePacket.cs" />
|
||||||
<Compile Include="packets\send\list\ListEntry.cs" />
|
<Compile Include="packets\send\groups\DeleteGroupPacket.cs" />
|
||||||
<Compile Include="packets\send\list\ListUtils.cs" />
|
<Compile Include="packets\send\groups\GroupHeaderPacket.cs" />
|
||||||
<Compile Include="packets\send\list\SetListPropertyPacket.cs" />
|
<Compile Include="packets\send\groups\GroupMember.cs" />
|
||||||
<Compile Include="packets\send\list\ListBeginPacket.cs" />
|
<Compile Include="packets\send\groups\GroupMembersBeginPacket.cs" />
|
||||||
<Compile Include="packets\send\list\ListEndPacket.cs" />
|
<Compile Include="packets\send\groups\GroupMembersEndPacket.cs" />
|
||||||
<Compile Include="packets\send\list\ListEntriesEndPacket.cs" />
|
<Compile Include="packets\send\groups\ContentMembersX08Packet.cs" />
|
||||||
<Compile Include="packets\send\list\ListStartPacket.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\GenericDataPacket.cs" />
|
||||||
<Compile Include="packets\send\player\SendAchievementRatePacket.cs" />
|
<Compile Include="packets\send\player\SendAchievementRatePacket.cs" />
|
||||||
<Compile Include="packets\send\player\SetCurrentJobPacket.cs" />
|
<Compile Include="packets\send\player\SetCurrentJobPacket.cs" />
|
||||||
@ -214,11 +237,10 @@
|
|||||||
<Compile Include="packets\send\Actor\SetActorTargetPacket.cs" />
|
<Compile Include="packets\send\Actor\SetActorTargetPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorStatusAllPacket.cs" />
|
<Compile Include="packets\send\Actor\SetActorStatusAllPacket.cs" />
|
||||||
<Compile Include="packets\send\login\0x2Packet.cs" />
|
<Compile Include="packets\send\login\0x2Packet.cs" />
|
||||||
<Compile Include="packets\send\Actor\AddActorPacket.cs" />
|
<Compile Include="packets\send\actor\AddActorPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\MoveActorToPositionPacket.cs" />
|
<Compile Include="packets\send\actor\MoveActorToPositionPacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorAppearancePacket.cs" />
|
<Compile Include="packets\send\actor\SetActorAppearancePacket.cs" />
|
||||||
<Compile Include="packets\send\Actor\SetActorPositionPacket.cs" />
|
<Compile Include="packets\send\actor\SetActorPositionPacket.cs" />
|
||||||
<Compile Include="packets\send\login\0x7ResponsePacket.cs" />
|
|
||||||
<Compile Include="packets\send\LogoutPacket.cs" />
|
<Compile Include="packets\send\LogoutPacket.cs" />
|
||||||
<Compile Include="packets\send\player\SetCompletedAchievementsPacket.cs" />
|
<Compile Include="packets\send\player\SetCompletedAchievementsPacket.cs" />
|
||||||
<Compile Include="packets\send\player\AchievementEarnedPacket.cs" />
|
<Compile Include="packets\send\player\AchievementEarnedPacket.cs" />
|
||||||
@ -228,9 +250,10 @@
|
|||||||
<Compile Include="packets\send\player\SetHasGoobbuePacket.cs" />
|
<Compile Include="packets\send\player\SetHasGoobbuePacket.cs" />
|
||||||
<Compile Include="packets\send\player\SetHasChocoboPacket.cs" />
|
<Compile Include="packets\send\player\SetHasChocoboPacket.cs" />
|
||||||
<Compile Include="packets\send\player\SetLatestAchievementsPacket.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\SetPlayerDreamPacket.cs" />
|
||||||
<Compile Include="packets\send\player\SetPlayerTitlePacket.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\PongPacket.cs" />
|
||||||
<Compile Include="packets\send\QuitPacket.cs" />
|
<Compile Include="packets\send\QuitPacket.cs" />
|
||||||
<Compile Include="packets\send\recruitment\CurrentRecruitmentDetailsPacket.cs" />
|
<Compile Include="packets\send\recruitment\CurrentRecruitmentDetailsPacket.cs" />
|
||||||
@ -258,12 +281,28 @@
|
|||||||
<Compile Include="packets\send\_0x02Packet.cs" />
|
<Compile Include="packets\send\_0x02Packet.cs" />
|
||||||
<Compile Include="packets\send\_0x10Packet.cs" />
|
<Compile Include="packets\send\_0x10Packet.cs" />
|
||||||
<Compile Include="packets\send\_0xE2Packet.cs" />
|
<Compile Include="packets\send\_0xE2Packet.cs" />
|
||||||
<Compile Include="packets\SubPacket.cs" />
|
|
||||||
<Compile Include="packets\receive\PingPacket.cs" />
|
<Compile Include="packets\receive\PingPacket.cs" />
|
||||||
<Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" />
|
<Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" />
|
||||||
|
<Compile Include="packets\WorldPackets\Receive\ErrorPacket.cs" />
|
||||||
|
<Compile Include="packets\WorldPackets\Receive\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="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="lua\LuaUtils.cs" />
|
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
@ -286,6 +325,7 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</None>
|
</None>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
<Compile Include="packets\WorldPackets\Send\WorldRequestZoneChangePacket.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
@ -295,9 +335,12 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent>xcopy "$(SolutionDir)data\map_config.ini" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d
|
<PostBuildEvent>
|
||||||
xcopy "$(SolutionDir)data\scripts" "$(SolutionDir)$(ProjectName)\$(OutDir)scripts\" /e /d /y /s
|
</PostBuildEvent>
|
||||||
xcopy "$(SolutionDir)data\staticactors.bin" "$(SolutionDir)$(ProjectName)\$(OutDir)" /d</PostBuildEvent>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<PreBuildEvent>
|
||||||
|
</PreBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
@ -38,13 +38,13 @@
|
|||||||
<target xsi:type="ColoredConsole" name="packets"
|
<target xsi:type="ColoredConsole" name="packets"
|
||||||
layout="${message}">
|
layout="${message}">
|
||||||
<highlight-row
|
<highlight-row
|
||||||
condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.BasePacket') and equals('${event-context:item=color}', '6')"
|
condition="equals('${logger}', 'FFXIVClassic.Common.BasePacket') and equals('${event-context:item=color}', '6')"
|
||||||
backgroundColor="DarkYellow" foregroundColor="NoChange" />
|
backgroundColor="DarkYellow" foregroundColor="NoChange" />
|
||||||
<highlight-row
|
<highlight-row
|
||||||
condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.SubPacket') and equals('${event-context:item=color}', '4')"
|
condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '4')"
|
||||||
backgroundColor="DarkRed" foregroundColor="NoChange" />
|
backgroundColor="DarkRed" foregroundColor="NoChange" />
|
||||||
<highlight-row
|
<highlight-row
|
||||||
condition="equals('${logger}', 'FFXIVClassic_Map_Server.packets.SubPacket') and equals('${event-context:item=color}', '5')"
|
condition="equals('${logger}', 'FFXIVClassic.Common.SubPacket') and equals('${event-context:item=color}', '5')"
|
||||||
backgroundColor="DarkMagenta" foregroundColor="NoChange" />
|
backgroundColor="DarkMagenta" foregroundColor="NoChange" />
|
||||||
</target>
|
</target>
|
||||||
</targets>
|
</targets>
|
||||||
@ -55,6 +55,7 @@
|
|||||||
<logger name='FFXIVClassic_Map_Server.Program' minlevel='Trace' writeTo='console' />
|
<logger name='FFXIVClassic_Map_Server.Program' minlevel='Trace' writeTo='console' />
|
||||||
<logger name='FFXIVClassic_Map_Server.lua.*' minlevel='Trace' writeTo='console' />
|
<logger name='FFXIVClassic_Map_Server.lua.*' minlevel='Trace' writeTo='console' />
|
||||||
<logger name='FFXIVClassic_Map_Server.packets.*' minlevel='Debug' writeTo='packets' />
|
<logger name='FFXIVClassic_Map_Server.packets.*' minlevel='Debug' writeTo='packets' />
|
||||||
|
<logger name='FFXIVClassic.Common.*' minlevel='Debug' writeTo='packets' />
|
||||||
<!--
|
<!--
|
||||||
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
|
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
|
||||||
<logger name="*" minlevel="Debug" writeTo="f" />
|
<logger name="*" minlevel="Debug" writeTo="f" />
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -18,408 +18,333 @@ using FFXIVClassic_Map_Server.packets.send.recruitment;
|
|||||||
using FFXIVClassic_Map_Server.packets.receive.events;
|
using FFXIVClassic_Map_Server.packets.receive.events;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
|
using FFXIVClassic_Map_Server.packets.WorldPackets.Send;
|
||||||
|
using FFXIVClassic_Map_Server.packets.WorldPackets.Receive;
|
||||||
|
using FFXIVClassic_Map_Server.actors.director;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server
|
namespace FFXIVClassic_Map_Server
|
||||||
{
|
{
|
||||||
class PacketProcessor
|
class PacketProcessor
|
||||||
{
|
{
|
||||||
Server mServer;
|
Server mServer;
|
||||||
CommandProcessor cp;
|
|
||||||
Dictionary<uint, ConnectedPlayer> mPlayers;
|
|
||||||
List<ClientConnection> mConnections;
|
|
||||||
|
|
||||||
public PacketProcessor(Server server, Dictionary<uint, ConnectedPlayer> playerList, List<ClientConnection> connectionList)
|
public PacketProcessor(Server server)
|
||||||
{
|
{
|
||||||
mPlayers = playerList;
|
|
||||||
mConnections = connectionList;
|
|
||||||
mServer = server;
|
mServer = server;
|
||||||
cp = new CommandProcessor(playerList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessPacket(ClientConnection client, BasePacket packet)
|
public void ProcessPacket(ZoneConnection client, SubPacket subpacket)
|
||||||
{
|
{
|
||||||
if (packet.header.isCompressed == 0x01)
|
Session session = mServer.GetSession(subpacket.header.sourceId);
|
||||||
BasePacket.DecryptPacket(client.blowfish, ref packet);
|
|
||||||
|
|
||||||
List<SubPacket> subPackets = packet.GetSubpackets();
|
if (session == null && subpacket.gameMessage.opcode != 0x1000)
|
||||||
foreach (SubPacket subpacket in subPackets)
|
return;
|
||||||
{
|
|
||||||
if (subpacket.header.type == 0x01)
|
//Normal Game Opcode
|
||||||
|
switch (subpacket.gameMessage.opcode)
|
||||||
{
|
{
|
||||||
packet.DebugPrintPacket();
|
//World Server - Error
|
||||||
byte[] reply1Data = {
|
case 0x100A:
|
||||||
0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
ErrorPacket worldError = new ErrorPacket(subpacket.data);
|
||||||
0x18, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFD, 0xFF, 0xFF,
|
switch (worldError.errorCode)
|
||||||
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);
|
case 0x01:
|
||||||
binReader.Write((UInt32)Utils.UnixTimeStampUTC());
|
session.GetActor().SendGameMessage(Server.GetWorldManager().GetActor(), 60005, 0x20);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Read in Actor Id that owns this connection
|
|
||||||
uint actorID = 0;
|
|
||||||
using (MemoryStream mem = new MemoryStream(packet.data))
|
|
||||||
{
|
|
||||||
using (BinaryReader binReader = new BinaryReader(mem))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] readIn = new byte[12];
|
|
||||||
binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
|
|
||||||
binReader.Read(readIn, 0, 12);
|
|
||||||
actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Should never happen.... unless actor id IS 0!
|
|
||||||
if (actorID == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
client.owner = actorID;
|
|
||||||
|
|
||||||
//Write Actor ID into reply2
|
|
||||||
using (MemoryStream mem = new MemoryStream(reply2.data))
|
|
||||||
{
|
|
||||||
using (BinaryWriter binReader = new BinaryWriter(mem))
|
|
||||||
{
|
|
||||||
binReader.BaseStream.Seek(0x10, SeekOrigin.Begin);
|
|
||||||
binReader.Write(actorID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectedPlayer player = null;
|
|
||||||
|
|
||||||
if (packet.header.connectionType == BasePacket.TYPE_ZONE)
|
|
||||||
{
|
|
||||||
while (mPlayers != null && !mPlayers.ContainsKey(client.owner))
|
|
||||||
{ }
|
|
||||||
player = mPlayers[client.owner];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create connected player if not Created
|
|
||||||
if (player == null)
|
|
||||||
{
|
|
||||||
player = new ConnectedPlayer(actorID);
|
|
||||||
mPlayers[actorID] = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.SetConnection(packet.header.connectionType, client);
|
|
||||||
|
|
||||||
if (packet.header.connectionType == BasePacket.TYPE_ZONE)
|
|
||||||
Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "zone", actorID, client.GetAddress());
|
|
||||||
else if (packet.header.connectionType == BasePacket.TYPE_CHAT)
|
|
||||||
Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "chat", actorID, client.GetAddress());
|
|
||||||
|
|
||||||
//Create player actor
|
|
||||||
reply1.DebugPrintPacket();
|
|
||||||
client.QueuePacket(reply1);
|
|
||||||
client.QueuePacket(reply2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (subpacket.header.type == 0x07)
|
|
||||||
{
|
|
||||||
BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x08);
|
|
||||||
//client.QueuePacket(init);
|
|
||||||
}
|
|
||||||
else if (subpacket.header.type == 0x08)
|
|
||||||
{
|
|
||||||
//Response, client's current [actorID][time]
|
|
||||||
//BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x07);
|
|
||||||
//client.QueuePacket(init);
|
|
||||||
packet.DebugPrintPacket();
|
|
||||||
}
|
|
||||||
else if (subpacket.header.type == 0x03)
|
|
||||||
{
|
|
||||||
ConnectedPlayer player = null;
|
|
||||||
|
|
||||||
if(mPlayers.ContainsKey(client.owner))
|
|
||||||
player = mPlayers[client.owner];
|
|
||||||
|
|
||||||
if (player == null || !player.IsClientConnectionsReady())
|
|
||||||
return;
|
|
||||||
|
|
||||||
//Normal Game Opcode
|
|
||||||
switch (subpacket.gameMessage.opcode)
|
|
||||||
{
|
|
||||||
//Ping
|
|
||||||
case 0x0001:
|
|
||||||
//subpacket.DebugPrintSubPacket();
|
|
||||||
PingPacket pingPacket = new PingPacket(subpacket.data);
|
|
||||||
client.QueuePacket(BasePacket.CreatePacket(PongPacket.BuildPacket(player.actorID, pingPacket.time), true, false));
|
|
||||||
player.Ping();
|
|
||||||
break;
|
|
||||||
//Unknown
|
|
||||||
case 0x0002:
|
|
||||||
|
|
||||||
subpacket.DebugPrintSubPacket();
|
|
||||||
client.QueuePacket(_0x2Packet.BuildPacket(player.actorID), true, false);
|
|
||||||
|
|
||||||
Server.GetWorldManager().DoLogin(player.GetActor());
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
//Chat Received
|
|
||||||
case 0x0003:
|
|
||||||
ChatMessagePacket chatMessage = new ChatMessagePacket(subpacket.data);
|
|
||||||
Program.Log.Info("Got type-{5} message: {0} @ {1}, {2}, {3}, Rot: {4}", chatMessage.message, chatMessage.posX, chatMessage.posY, chatMessage.posZ, chatMessage.posRot, chatMessage.logType);
|
|
||||||
subpacket.DebugPrintSubPacket();
|
|
||||||
|
|
||||||
if (chatMessage.message.StartsWith("!"))
|
|
||||||
{
|
|
||||||
if (cp.DoCommand(chatMessage.message, player))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.GetActor().BroadcastPacket(SendMessagePacket.BuildPacket(player.actorID, player.actorID, chatMessage.logType, player.GetActor().customDisplayName, chatMessage.message), false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
//Langauge Code
|
|
||||||
case 0x0006:
|
|
||||||
LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
|
|
||||||
player.languageCode = langCode.languageCode;
|
|
||||||
break;
|
|
||||||
//Unknown - Happens a lot at login, then once every time player zones
|
|
||||||
case 0x0007:
|
|
||||||
//subpacket.DebugPrintSubPacket();
|
|
||||||
_0x07Packet unknown07 = new _0x07Packet(subpacket.data);
|
|
||||||
break;
|
|
||||||
//Update Position
|
|
||||||
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();
|
|
||||||
|
|
||||||
if (player.GetActor().IsInZoneChange())
|
|
||||||
player.GetActor().SetZoneChanging(false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
//Set Target
|
|
||||||
case 0x00CD:
|
|
||||||
//subpacket.DebugPrintSubPacket();
|
|
||||||
|
|
||||||
SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
|
|
||||||
player.GetActor().currentTarget = setTarget.actorID;
|
|
||||||
player.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(player.actorID, player.actorID, setTarget.actorID), true);
|
|
||||||
break;
|
|
||||||
//Lock Target
|
|
||||||
case 0x00CC:
|
|
||||||
LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
|
|
||||||
player.GetActor().currentLockedTarget = lockTarget.actorID;
|
|
||||||
break;
|
|
||||||
//Start Event
|
|
||||||
case 0x012D:
|
|
||||||
subpacket.DebugPrintSubPacket();
|
|
||||||
EventStartPacket eventStart = new EventStartPacket(subpacket.data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (eventStart.error != null)
|
|
||||||
{
|
|
||||||
player.errorMessage += eventStart.error;
|
|
||||||
|
|
||||||
if (eventStart.errorIndex == eventStart.errorNum - 1)
|
|
||||||
Program.Log.Error("\n"+player.errorMessage);
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*/
|
break;
|
||||||
|
//World Server - Session Begin
|
||||||
|
case 0x1000:
|
||||||
|
subpacket.DebugPrintSubPacket();
|
||||||
|
|
||||||
Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
|
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);
|
||||||
|
session.QueuePacket(PongPacket.BuildPacket(session.id, pingPacket.time));
|
||||||
|
session.Ping();
|
||||||
|
break;
|
||||||
|
//Unknown
|
||||||
|
case 0x0002:
|
||||||
|
|
||||||
|
subpacket.DebugPrintSubPacket();
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (chatMessage.message.StartsWith("!"))
|
||||||
|
{
|
||||||
|
if (Server.GetCommandProcessor().DoCommand(chatMessage.message, session))
|
||||||
|
return; ;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (Client safe to send packets to now)
|
||||||
|
case 0x0006:
|
||||||
|
LangaugeCodePacket langCode = new LangaugeCodePacket(subpacket.data);
|
||||||
|
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();
|
||||||
|
ZoneInCompletePacket zoneInCompletePacket = new ZoneInCompletePacket(subpacket.data);
|
||||||
|
break;
|
||||||
|
//Update Position
|
||||||
|
case 0x00CA:
|
||||||
|
//Update Position
|
||||||
|
UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
|
||||||
|
session.UpdatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
|
||||||
|
session.GetActor().SendInstanceUpdate();
|
||||||
|
|
||||||
|
if (session.GetActor().IsInZoneChange())
|
||||||
|
session.GetActor().SetZoneChanging(false);
|
||||||
|
|
||||||
|
break;
|
||||||
|
//Set Target
|
||||||
|
case 0x00CD:
|
||||||
|
//subpacket.DebugPrintSubPacket();
|
||||||
|
|
||||||
|
SetTargetPacket setTarget = new SetTargetPacket(subpacket.data);
|
||||||
|
session.GetActor().currentTarget = setTarget.actorID;
|
||||||
|
session.GetActor().BroadcastPacket(SetActorTargetAnimatedPacket.BuildPacket(session.id, setTarget.actorID), true);
|
||||||
|
break;
|
||||||
|
//Lock Target
|
||||||
|
case 0x00CC:
|
||||||
|
LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data);
|
||||||
|
session.GetActor().currentLockedTarget = lockTarget.actorID;
|
||||||
|
break;
|
||||||
|
//Start Event
|
||||||
|
case 0x012D:
|
||||||
|
subpacket.DebugPrintSubPacket();
|
||||||
|
EventStartPacket eventStart = new EventStartPacket(subpacket.data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (eventStart.error != null)
|
||||||
|
{
|
||||||
|
player.errorMessage += eventStart.error;
|
||||||
|
|
||||||
|
if (eventStart.errorIndex == eventStart.errorNum - 1)
|
||||||
|
Program.Log.Error("\n"+player.errorMessage);
|
||||||
|
|
||||||
|
|
||||||
player.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
|
break;
|
||||||
player.GetActor().currentEventName = eventStart.triggerName;
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Actor ownerActor = Server.GetStaticActors(eventStart.scriptOwnerActorID);
|
||||||
|
|
||||||
|
|
||||||
|
session.GetActor().currentEventOwner = eventStart.scriptOwnerActorID;
|
||||||
|
session.GetActor().currentEventName = eventStart.triggerName;
|
||||||
|
|
||||||
|
|
||||||
|
if (ownerActor == null)
|
||||||
|
{
|
||||||
|
//Is it a instance actor?
|
||||||
|
ownerActor = session.GetActor().zone.FindActorInArea(session.GetActor().currentEventOwner);
|
||||||
if (ownerActor == null)
|
if (ownerActor == null)
|
||||||
{
|
{
|
||||||
//Is it a instance actor?
|
//Is it a Director?
|
||||||
ownerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
|
Director director = session.GetActor().GetDirector(eventStart.scriptOwnerActorID);
|
||||||
if (ownerActor == null)
|
if (director != null)
|
||||||
|
ownerActor = director;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//Is it a Director?
|
Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
|
||||||
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
|
break;
|
||||||
ownerActor = player.GetActor().currentDirector;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Program.Log.Debug("\n===Event START===\nCould not find actor 0x{0:X} for event started by caller: 0x{1:X}\nEvent Starter: {2}\nParams: {3}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
player.GetActor().StartEvent(ownerActor, eventStart);
|
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:
|
||||||
|
subpacket.DebugPrintSubPacket();
|
||||||
|
EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data);
|
||||||
|
Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
|
||||||
|
/*
|
||||||
|
//Is it a static actor? If not look in the player's instance
|
||||||
|
Actor updateOwnerActor = Server.GetStaticActors(session.GetActor().currentEventOwner);
|
||||||
|
if (updateOwnerActor == null)
|
||||||
|
{
|
||||||
|
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(session.GetActor().currentEventOwner);
|
||||||
|
|
||||||
|
if (session.GetActor().currentDirector != null && session.GetActor().currentEventOwner == session.GetActor().currentDirector.actorId)
|
||||||
|
updateOwnerActor = session.GetActor().currentDirector;
|
||||||
|
|
||||||
Program.Log.Debug("\n===Event START===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nEvent Starter: {4}\nParams: {5}", eventStart.actorID, eventStart.scriptOwnerActorID, eventStart.val1, eventStart.val2, eventStart.triggerName, LuaUtils.DumpParams(eventStart.luaParams));
|
|
||||||
break;
|
|
||||||
//Unknown, happens at npc spawn and cutscene play????
|
|
||||||
case 0x00CE:
|
|
||||||
break;
|
|
||||||
//Event Result
|
|
||||||
case 0x012E:
|
|
||||||
subpacket.DebugPrintSubPacket();
|
|
||||||
EventUpdatePacket eventUpdate = new EventUpdatePacket(subpacket.data);
|
|
||||||
Program.Log.Debug("\n===Event UPDATE===\nSource Actor: 0x{0:X}\nCaller Actor: 0x{1:X}\nVal1: 0x{2:X}\nVal2: 0x{3:X}\nStep: 0x{4:X}\nParams: {5}", eventUpdate.actorID, eventUpdate.scriptOwnerActorID, eventUpdate.val1, eventUpdate.val2, eventUpdate.step, LuaUtils.DumpParams(eventUpdate.luaParams));
|
|
||||||
/*
|
|
||||||
//Is it a static actor? If not look in the player's instance
|
|
||||||
Actor updateOwnerActor = Server.GetStaticActors(player.GetActor().currentEventOwner);
|
|
||||||
if (updateOwnerActor == null)
|
if (updateOwnerActor == null)
|
||||||
{
|
break;
|
||||||
updateOwnerActor = Server.GetWorldManager().GetActorInWorld(player.GetActor().currentEventOwner);
|
}
|
||||||
|
*/
|
||||||
|
session.GetActor().UpdateEvent(eventUpdate);
|
||||||
|
|
||||||
if (player.GetActor().currentDirector != null && player.GetActor().currentEventOwner == player.GetActor().currentDirector.actorId)
|
//LuaEngine.DoActorOnEventUpdated(session.GetActor(), updateOwnerActor, eventUpdate);
|
||||||
updateOwnerActor = player.GetActor().currentDirector;
|
|
||||||
|
|
||||||
if (updateOwnerActor == null)
|
break;
|
||||||
break;
|
case 0x012F:
|
||||||
}
|
subpacket.DebugPrintSubPacket();
|
||||||
*/
|
ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
|
||||||
player.GetActor().UpdateEvent(eventUpdate);
|
if (paramRequest.paramName.Equals("charaWork/exp"))
|
||||||
|
session.GetActor().SendCharaExpInfo();
|
||||||
//LuaEngine.DoActorOnEventUpdated(player.GetActor(), updateOwnerActor, eventUpdate);
|
break;
|
||||||
|
//Group Created Confirm
|
||||||
break;
|
case 0x0133:
|
||||||
case 0x012F:
|
GroupCreatedPacket groupCreated = new GroupCreatedPacket(subpacket.data);
|
||||||
//subpacket.DebugPrintSubPacket();
|
Server.GetWorldManager().SendGroupInit(session, groupCreated.groupId);
|
||||||
ParameterDataRequestPacket paramRequest = new ParameterDataRequestPacket(subpacket.data);
|
break;
|
||||||
if (paramRequest.paramName.Equals("charaWork/exp"))
|
/* RECRUITMENT */
|
||||||
player.GetActor().SendCharaExpInfo();
|
//Start Recruiting
|
||||||
break;
|
case 0x01C3:
|
||||||
/* RECRUITMENT */
|
StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
|
||||||
//Start Recruiting
|
session.QueuePacket(StartRecruitingResponse.BuildPacket(session.id, true));
|
||||||
case 0x01C3:
|
break;
|
||||||
StartRecruitingRequestPacket recruitRequestPacket = new StartRecruitingRequestPacket(subpacket.data);
|
//End Recruiting
|
||||||
client.QueuePacket(BasePacket.CreatePacket(StartRecruitingResponse.BuildPacket(player.actorID, true), true, false));
|
case 0x01C4:
|
||||||
break;
|
session.QueuePacket(EndRecruitmentPacket.BuildPacket(session.id));
|
||||||
//End Recruiting
|
break;
|
||||||
case 0x01C4:
|
//Party Window Opened, Request State
|
||||||
client.QueuePacket(BasePacket.CreatePacket(EndRecruitmentPacket.BuildPacket(player.actorID), true, false));
|
case 0x01C5:
|
||||||
break;
|
session.QueuePacket(RecruiterStatePacket.BuildPacket(session.id, false, false, 0));
|
||||||
//Party Window Opened, Request State
|
break;
|
||||||
case 0x01C5:
|
//Search Recruiting
|
||||||
client.QueuePacket(BasePacket.CreatePacket(RecruiterStatePacket.BuildPacket(player.actorID, true, true, 1), true, false));
|
case 0x01C7:
|
||||||
break;
|
RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data);
|
||||||
//Search Recruiting
|
break;
|
||||||
case 0x01C7:
|
//Get Recruitment Details
|
||||||
RecruitmentSearchRequestPacket recruitSearchPacket = new RecruitmentSearchRequestPacket(subpacket.data);
|
case 0x01C8:
|
||||||
break;
|
RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data);
|
||||||
//Get Recruitment Details
|
RecruitmentDetails details = new RecruitmentDetails();
|
||||||
case 0x01C8:
|
details.recruiterName = "Localhost Character";
|
||||||
RecruitmentDetailsRequestPacket currentRecruitDetailsPacket = new RecruitmentDetailsRequestPacket(subpacket.data);
|
details.purposeId = 2;
|
||||||
RecruitmentDetails details = new RecruitmentDetails();
|
details.locationId = 1;
|
||||||
details.recruiterName = "Localhost Character";
|
details.subTaskId = 1;
|
||||||
details.purposeId = 2;
|
details.comment = "This is a test details packet sent by the server. No implementation has been Created yet...";
|
||||||
details.locationId = 1;
|
details.num[0] = 1;
|
||||||
details.subTaskId = 1;
|
session.QueuePacket(CurrentRecruitmentDetailsPacket.BuildPacket(session.id, details));
|
||||||
details.comment = "This is a test details packet sent by the server. No implementation has been Created yet...";
|
break;
|
||||||
details.num[0] = 1;
|
//Accepted Recruiting
|
||||||
client.QueuePacket(BasePacket.CreatePacket(CurrentRecruitmentDetailsPacket.BuildPacket(player.actorID, details), true, false));
|
case 0x01C6:
|
||||||
break;
|
subpacket.DebugPrintSubPacket();
|
||||||
//Accepted Recruiting
|
break;
|
||||||
case 0x01C6:
|
/* SOCIAL STUFF */
|
||||||
subpacket.DebugPrintSubPacket();
|
case 0x01C9:
|
||||||
break;
|
AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data);
|
||||||
/* SOCIAL STUFF */
|
session.QueuePacket(BlacklistAddedPacket.BuildPacket(session.id, true, addBlackList.name));
|
||||||
case 0x01C9:
|
break;
|
||||||
AddRemoveSocialPacket addBlackList = new AddRemoveSocialPacket(subpacket.data);
|
case 0x01CA:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(BlacklistAddedPacket.BuildPacket(player.actorID, true, addBlackList.name), true, false));
|
AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data);
|
||||||
break;
|
session.QueuePacket(BlacklistRemovedPacket.BuildPacket(session.id, true, RemoveBlackList.name));
|
||||||
case 0x01CA:
|
break;
|
||||||
AddRemoveSocialPacket RemoveBlackList = new AddRemoveSocialPacket(subpacket.data);
|
case 0x01CB:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(BlacklistRemovedPacket.BuildPacket(player.actorID, true, RemoveBlackList.name), true, false));
|
int offset1 = 0;
|
||||||
break;
|
session.QueuePacket(SendBlacklistPacket.BuildPacket(session.id, new String[] { "Test" }, ref offset1));
|
||||||
case 0x01CB:
|
break;
|
||||||
int offset1 = 0;
|
case 0x01CC:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(SendBlacklistPacket.BuildPacket(player.actorID, new String[] { "Test" }, ref offset1), true, false));
|
AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data);
|
||||||
break;
|
session.QueuePacket(FriendlistAddedPacket.BuildPacket(session.id, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name));
|
||||||
case 0x01CC:
|
break;
|
||||||
AddRemoveSocialPacket addFriendList = new AddRemoveSocialPacket(subpacket.data);
|
case 0x01CD:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(FriendlistAddedPacket.BuildPacket(player.actorID, true, (uint)addFriendList.name.GetHashCode(), true, addFriendList.name), true, false));
|
AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
|
||||||
break;
|
session.QueuePacket(FriendlistRemovedPacket.BuildPacket(session.id, true, RemoveFriendList.name));
|
||||||
case 0x01CD:
|
break;
|
||||||
AddRemoveSocialPacket RemoveFriendList = new AddRemoveSocialPacket(subpacket.data);
|
case 0x01CE:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(FriendlistRemovedPacket.BuildPacket(player.actorID, true, RemoveFriendList.name), true, false));
|
int offset2 = 0;
|
||||||
break;
|
session.QueuePacket(SendFriendlistPacket.BuildPacket(session.id, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2));
|
||||||
case 0x01CE:
|
break;
|
||||||
int offset2 = 0;
|
case 0x01CF:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(SendFriendlistPacket.BuildPacket(player.actorID, new Tuple<long, string>[] { new Tuple<long, string>(01, "Test2") }, ref offset2), true, false));
|
session.QueuePacket(FriendStatusPacket.BuildPacket(session.id, null));
|
||||||
break;
|
break;
|
||||||
case 0x01CF:
|
/* SUPPORT DESK STUFF */
|
||||||
client.QueuePacket(BasePacket.CreatePacket(FriendStatusPacket.BuildPacket(player.actorID, null), true, false));
|
//Request for FAQ/Info List
|
||||||
break;
|
case 0x01D0:
|
||||||
/* SUPPORT DESK STUFF */
|
FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data);
|
||||||
//Request for FAQ/Info List
|
session.QueuePacket(FaqListResponsePacket.BuildPacket(session.id, new string[] { "Testing FAQ1", "Coded style!" }));
|
||||||
case 0x01D0:
|
break;
|
||||||
FaqListRequestPacket faqRequest = new FaqListRequestPacket(subpacket.data);
|
//Request for body of a faq/info selection
|
||||||
client.QueuePacket(BasePacket.CreatePacket(FaqListResponsePacket.BuildPacket(player.actorID, Database.getFAQNames(faqRequest.langCode)), true, false));
|
case 0x01D1:
|
||||||
break;
|
FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data);
|
||||||
//Request for body of a faq/info selection
|
session.QueuePacket(FaqBodyResponsePacket.BuildPacket(session.id, "HERE IS A GIANT BODY. Nothing else to say!"));
|
||||||
case 0x01D1:
|
break;
|
||||||
FaqBodyRequestPacket faqBodyRequest = new FaqBodyRequestPacket(subpacket.data);
|
//Request issue list
|
||||||
client.QueuePacket(BasePacket.CreatePacket(FaqBodyResponsePacket.BuildPacket(player.actorID, Database.getFAQBody(faqBodyRequest.faqIndex, faqBodyRequest.langCode)), true, false));
|
case 0x01D2:
|
||||||
break;
|
GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
|
||||||
//Request issue list
|
session.QueuePacket(IssueListResponsePacket.BuildPacket(session.id, new string[] { "Test1", "Test2", "Test3", "Test4", "Test5" }));
|
||||||
case 0x01D2:
|
break;
|
||||||
GMTicketIssuesRequestPacket issuesRequest = new GMTicketIssuesRequestPacket(subpacket.data);
|
//Request if GM ticket exists
|
||||||
client.QueuePacket(BasePacket.CreatePacket(IssueListResponsePacket.BuildPacket(player.actorID, Database.getIssues(issuesRequest.langCode)), true, false));
|
case 0x01D3:
|
||||||
break;
|
session.QueuePacket(StartGMTicketPacket.BuildPacket(session.id, false));
|
||||||
//Request if GM ticket exists
|
break;
|
||||||
case 0x01D3:
|
//Request for GM response message
|
||||||
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, Database.isTicketOpen(player.GetActor().customDisplayName)), true, false));
|
case 0x01D4:
|
||||||
break;
|
session.QueuePacket(GMTicketPacket.BuildPacket(session.id, "This is a GM Ticket Title", "This is a GM Ticket Body."));
|
||||||
//Request for GM response message
|
break;
|
||||||
case 0x01D4:
|
//GM Ticket Sent
|
||||||
client.QueuePacket(BasePacket.CreatePacket(GMTicketPacket.BuildPacket(player.actorID, "Ticket Title", "Enter your Help request here."), true, false));
|
case 0x01D5:
|
||||||
break;
|
GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
|
||||||
//GM Ticket Sent
|
Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
|
||||||
case 0x01D5:
|
session.QueuePacket(GMTicketSentResponsePacket.BuildPacket(session.id, true));
|
||||||
GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data);
|
break;
|
||||||
Program.Log.Info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody);
|
//Request to end ticket
|
||||||
bool wasError = Database.SaveSupportTicket(gmTicket, player.GetActor().customDisplayName);
|
case 0x01D6:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(GMTicketSentResponsePacket.BuildPacket(player.actorID, !wasError), true, false));
|
session.QueuePacket(EndGMTicketPacket.BuildPacket(session.id));
|
||||||
|
break;
|
||||||
if (!wasError)
|
default:
|
||||||
client.QueuePacket(BasePacket.CreatePacket(StartGMTicketPacket.BuildPacket(player.actorID, true), true, false));
|
Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
|
||||||
|
subpacket.DebugPrintSubPacket();
|
||||||
break;
|
break;
|
||||||
//Request to end ticket
|
|
||||||
case 0x01D6:
|
|
||||||
Database.closeTicket(player.GetActor().customDisplayName);
|
|
||||||
client.QueuePacket(BasePacket.CreatePacket(EndGMTicketPacket.BuildPacket(player.actorID), true, false));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Program.Log.Debug("Unknown command 0x{0:X} received.", subpacket.gameMessage.opcode);
|
|
||||||
subpacket.DebugPrintSubPacket();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
packet.DebugPrintPacket();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ namespace FFXIVClassic_Map_Server
|
|||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
|
||||||
// set up logging
|
// set up logging
|
||||||
Log = LogManager.GetCurrentClassLogger();
|
Log = LogManager.GetCurrentClassLogger();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -28,11 +27,14 @@ namespace FFXIVClassic_Map_Server
|
|||||||
#endif
|
#endif
|
||||||
bool startServer = true;
|
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
|
//Load Config
|
||||||
if (!ConfigConstants.Load())
|
ConfigConstants.Load();
|
||||||
startServer = false;
|
ConfigConstants.ApplyLaunchArgs(args);
|
||||||
|
|
||||||
//Test DB Connection
|
//Test DB Connection
|
||||||
Program.Log.Info("Testing 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
|
//Start server if A-OK
|
||||||
if (startServer)
|
if (startServer)
|
||||||
{
|
{
|
||||||
Server server = new Server();
|
Server server = new Server();
|
||||||
CommandProcessor cp = new CommandProcessor(server.GetConnectedPlayerList());
|
|
||||||
server.StartServer();
|
server.StartServer();
|
||||||
|
|
||||||
while (startServer)
|
while (startServer)
|
||||||
{
|
{
|
||||||
String input = Console.ReadLine();
|
String input = Console.ReadLine();
|
||||||
Log.Info("[Console Input] " + input);
|
Log.Info("[Console Input] " + input);
|
||||||
cp.DoCommand(input, null);
|
Server.GetCommandProcessor().DoCommand(input, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using NLog;
|
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
|
|
||||||
@ -17,7 +15,6 @@ namespace FFXIVClassic_Map_Server
|
|||||||
public const int FFXIV_MAP_PORT = 54992;
|
public const int FFXIV_MAP_PORT = 54992;
|
||||||
public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF
|
public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF
|
||||||
public const int BACKLOG = 100;
|
public const int BACKLOG = 100;
|
||||||
public const int HEALTH_THREAD_SLEEP_TIME = 5;
|
|
||||||
|
|
||||||
public const string STATIC_ACTORS_PATH = "./staticactors.bin";
|
public const string STATIC_ACTORS_PATH = "./staticactors.bin";
|
||||||
|
|
||||||
@ -25,60 +22,30 @@ namespace FFXIVClassic_Map_Server
|
|||||||
|
|
||||||
private Socket mServerSocket;
|
private Socket mServerSocket;
|
||||||
|
|
||||||
private Dictionary<uint, ConnectedPlayer> mConnectedPlayerList = new Dictionary<uint, ConnectedPlayer>();
|
private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();
|
||||||
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
|
|
||||||
private LuaEngine mLuaEngine = new LuaEngine();
|
|
||||||
|
|
||||||
|
private static CommandProcessor mCommandProcessor = new CommandProcessor();
|
||||||
|
private static ZoneConnection mWorldConnection = new ZoneConnection();
|
||||||
private static WorldManager mWorldManager;
|
private static WorldManager mWorldManager;
|
||||||
private static Dictionary<uint, Item> gamedataItems;
|
private static Dictionary<uint, ItemData> mGamedataItems;
|
||||||
|
private static Dictionary<uint, GuildleveData> mGamedataGuildleves;
|
||||||
private static StaticActors mStaticActors;
|
private static StaticActors mStaticActors;
|
||||||
|
|
||||||
private PacketProcessor mProcessor;
|
private PacketProcessor mProcessor;
|
||||||
|
|
||||||
private Thread mConnectionHealthThread;
|
|
||||||
private bool killHealthThread = false;
|
|
||||||
|
|
||||||
private void ConnectionHealth()
|
|
||||||
{
|
|
||||||
Program.Log.Info("Connection Health thread started; it will run every {0} seconds.", HEALTH_THREAD_SLEEP_TIME);
|
|
||||||
while (!killHealthThread)
|
|
||||||
{
|
|
||||||
lock (mConnectedPlayerList)
|
|
||||||
{
|
|
||||||
List<ConnectedPlayer> dcedPlayers = new List<ConnectedPlayer>();
|
|
||||||
foreach (ConnectedPlayer cp in mConnectedPlayerList.Values)
|
|
||||||
{
|
|
||||||
if (cp.CheckIfDCing())
|
|
||||||
dcedPlayers.Add(cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (ConnectedPlayer cp in dcedPlayers)
|
|
||||||
cp.GetActor().CleanupAndSave();
|
|
||||||
}
|
|
||||||
Thread.Sleep(HEALTH_THREAD_SLEEP_TIME * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Server()
|
public Server()
|
||||||
{
|
{
|
||||||
mSelf = this;
|
mSelf = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Server GetServer()
|
|
||||||
{
|
|
||||||
return mSelf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool StartServer()
|
public bool StartServer()
|
||||||
{
|
{
|
||||||
mConnectionHealthThread = new Thread(new ThreadStart(ConnectionHealth));
|
|
||||||
mConnectionHealthThread.Name = "MapThread:Health";
|
|
||||||
//mConnectionHealthThread.Start();
|
|
||||||
|
|
||||||
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
|
mStaticActors = new StaticActors(STATIC_ACTORS_PATH);
|
||||||
|
|
||||||
gamedataItems = Database.GetItemGamedata();
|
mGamedataItems = Database.GetItemGamedata();
|
||||||
Program.Log.Info("Loaded {0} items.", gamedataItems.Count);
|
Program.Log.Info("Loaded {0} items.", mGamedataItems.Count);
|
||||||
|
mGamedataGuildleves = Database.GetGuildleveGamedata();
|
||||||
|
Program.Log.Info("Loaded {0} guildleves.", mGamedataGuildleves.Count);
|
||||||
|
|
||||||
mWorldManager = new WorldManager(this);
|
mWorldManager = new WorldManager(this);
|
||||||
mWorldManager.LoadZoneList();
|
mWorldManager.LoadZoneList();
|
||||||
@ -87,12 +54,13 @@ namespace FFXIVClassic_Map_Server
|
|||||||
mWorldManager.LoadActorClasses();
|
mWorldManager.LoadActorClasses();
|
||||||
mWorldManager.LoadSpawnLocations();
|
mWorldManager.LoadSpawnLocations();
|
||||||
mWorldManager.SpawnAllActors();
|
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
|
try
|
||||||
{
|
{
|
||||||
mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
mServerSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -120,39 +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);
|
Program.Log.Info("Map Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
|
|
||||||
mProcessor = new PacketProcessor(this, mConnectedPlayerList, mConnectionList);
|
mProcessor = new PacketProcessor(this);
|
||||||
|
|
||||||
//mGameThread = new Thread(new ThreadStart(mProcessor.update));
|
//mGameThread = new Thread(new ThreadStart(mProcessor.update));
|
||||||
//mGameThread.Start();
|
//mGameThread.Start();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovePlayer(Player player)
|
#region Session Handling
|
||||||
|
|
||||||
|
public Session AddSession(uint id)
|
||||||
{
|
{
|
||||||
lock (mConnectedPlayerList)
|
if (mSessionList.ContainsKey(id))
|
||||||
|
return mSessionList[id];
|
||||||
|
|
||||||
|
Session session = new Session(id);
|
||||||
|
mSessionList.Add(id, session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveSession(uint id)
|
||||||
|
{
|
||||||
|
if (mSessionList.ContainsKey(id))
|
||||||
{
|
{
|
||||||
if (mConnectedPlayerList.ContainsKey(player.actorId))
|
mSessionList.Remove(id);
|
||||||
mConnectedPlayerList.Remove(player.actorId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Session GetSession(uint id)
|
||||||
|
{
|
||||||
|
if (mSessionList.ContainsKey(id))
|
||||||
|
return mSessionList[id];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session GetSession(string name)
|
||||||
|
{
|
||||||
|
foreach (Session s in mSessionList.Values)
|
||||||
|
{
|
||||||
|
if (s.GetActor().customDisplayName.ToLower().Equals(name.ToLower()))
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<uint, Session> GetSessionList()
|
||||||
|
{
|
||||||
|
return mSessionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Socket Handling
|
#region Socket Handling
|
||||||
private void AcceptCallback(IAsyncResult result)
|
private void AcceptCallback(IAsyncResult result)
|
||||||
{
|
{
|
||||||
ClientConnection conn = null;
|
ZoneConnection conn = null;
|
||||||
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
|
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
conn = new ClientConnection();
|
conn = new ZoneConnection();
|
||||||
conn.socket = socket.EndAccept(result);
|
conn.socket = socket.EndAccept(result);
|
||||||
conn.buffer = new byte[BUFFER_SIZE];
|
conn.buffer = new byte[BUFFER_SIZE];
|
||||||
|
|
||||||
lock (mConnectionList)
|
mWorldConnection = conn;
|
||||||
{
|
|
||||||
mConnectionList.Add(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port);
|
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port);
|
||||||
//Queue recieving of data from the connection
|
//Queue recieving of data from the connection
|
||||||
@ -164,11 +165,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
if (conn != null)
|
if (conn != null)
|
||||||
{
|
{
|
||||||
|
mWorldConnection = null;
|
||||||
lock (mConnectionList)
|
|
||||||
{
|
|
||||||
mConnectionList.Remove(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||||
}
|
}
|
||||||
@ -176,53 +173,25 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
if (conn != null)
|
if (conn != null)
|
||||||
{
|
{
|
||||||
lock (mConnectionList)
|
mWorldConnection = null;
|
||||||
{
|
|
||||||
mConnectionList.Remove(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Actor GetStaticActors(uint id)
|
|
||||||
{
|
|
||||||
return mStaticActors.GetActor(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Actor GetStaticActors(string name)
|
|
||||||
{
|
|
||||||
return mStaticActors.FindStaticActor(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Item GetItemGamedata(uint id)
|
|
||||||
{
|
|
||||||
if (gamedataItems.ContainsKey(id))
|
|
||||||
return gamedataItems[id];
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend.
|
/// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="result"></param>
|
/// <param name="result"></param>
|
||||||
private void ReceiveCallback(IAsyncResult result)
|
private void ReceiveCallback(IAsyncResult result)
|
||||||
{
|
{
|
||||||
ClientConnection conn = (ClientConnection)result.AsyncState;
|
ZoneConnection conn = (ZoneConnection)result.AsyncState;
|
||||||
|
|
||||||
//Check if disconnected
|
//Check if disconnected
|
||||||
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
|
if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0))
|
||||||
{
|
{
|
||||||
if (mConnectedPlayerList.ContainsKey(conn.owner))
|
mWorldConnection = null;
|
||||||
mConnectedPlayerList.Remove(conn.owner);
|
Program.Log.Info("Disconnected from world server!");
|
||||||
lock (mConnectionList)
|
|
||||||
{
|
|
||||||
mConnectionList.Remove(conn);
|
|
||||||
}
|
|
||||||
if (conn.connType == BasePacket.TYPE_ZONE)
|
|
||||||
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -238,13 +207,13 @@ namespace FFXIVClassic_Map_Server
|
|||||||
//Build packets until can no longer or out of data
|
//Build packets until can no longer or out of data
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
BasePacket basePacket = BuildPacket(ref offset, conn.buffer, bytesRead);
|
SubPacket subPacket = SubPacket.CreatePacket(ref offset, conn.buffer, bytesRead);
|
||||||
|
|
||||||
//If can't build packet, break, else process another
|
//If can't build packet, break, else process another
|
||||||
if (basePacket == null)
|
if (subPacket == null)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
mProcessor.ProcessPacket(conn, basePacket);
|
mProcessor.ProcessPacket(conn, subPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Not all bytes consumed, transfer leftover to beginning
|
//Not all bytes consumed, transfer leftover to beginning
|
||||||
@ -265,79 +234,71 @@ namespace FFXIVClassic_Map_Server
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
|
mWorldConnection = null;
|
||||||
|
Program.Log.Info("Disconnected from world server!");
|
||||||
lock (mConnectionList)
|
|
||||||
{
|
|
||||||
mConnectionList.Remove(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SocketException)
|
catch (SocketException)
|
||||||
{
|
{
|
||||||
if (conn.socket != null)
|
if (conn.socket != null)
|
||||||
{
|
{
|
||||||
Program.Log.Info("{0} has disconnected.", conn.owner == 0 ? conn.GetAddress() : "User " + conn.owner);
|
mWorldConnection = null;
|
||||||
|
Program.Log.Info("Disconnected from world server!");
|
||||||
lock (mConnectionList)
|
|
||||||
{
|
|
||||||
mConnectionList.Remove(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">Current offset in buffer.</param>
|
|
||||||
/// <param name="buffer">Incoming buffer.</param>
|
|
||||||
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
|
|
||||||
public BasePacket BuildPacket(ref int offset, byte[] buffer, int bytesRead)
|
|
||||||
{
|
|
||||||
BasePacket newPacket = null;
|
|
||||||
|
|
||||||
//Too small to even get length
|
|
||||||
if (bytesRead <= offset)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
ushort packetSize = BitConverter.ToUInt16(buffer, offset);
|
|
||||||
|
|
||||||
//Too small to whole packet
|
|
||||||
if (bytesRead < offset + packetSize)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (buffer.Length < offset + packetSize)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newPacket = new BasePacket(buffer, ref offset);
|
|
||||||
}
|
|
||||||
catch (OverflowException)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public static ZoneConnection GetWorldConnection()
|
||||||
|
{
|
||||||
|
return mWorldConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Server GetServer()
|
||||||
|
{
|
||||||
|
return mSelf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommandProcessor GetCommandProcessor()
|
||||||
|
{
|
||||||
|
return mCommandProcessor;
|
||||||
|
}
|
||||||
|
|
||||||
public static WorldManager GetWorldManager()
|
public static WorldManager GetWorldManager()
|
||||||
{
|
{
|
||||||
return mWorldManager;
|
return mWorldManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<uint, ConnectedPlayer> GetConnectedPlayerList()
|
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.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
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
|
namespace FFXIVClassic_Map_Server
|
||||||
{
|
{
|
||||||
@ -27,9 +34,18 @@ namespace FFXIVClassic_Map_Server
|
|||||||
private Dictionary<uint, List<SeamlessBoundry>> seamlessBoundryList;
|
private Dictionary<uint, List<SeamlessBoundry>> seamlessBoundryList;
|
||||||
private Dictionary<uint, ZoneEntrance> zoneEntranceList;
|
private Dictionary<uint, ZoneEntrance> zoneEntranceList;
|
||||||
private Dictionary<uint, ActorClass> actorClasses = new Dictionary<uint,ActorClass>();
|
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 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)
|
public WorldManager(Server server)
|
||||||
{
|
{
|
||||||
mServer = server;
|
mServer = server;
|
||||||
@ -52,7 +68,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
id,
|
id,
|
||||||
zoneName,
|
zoneName,
|
||||||
regionId,
|
regionId,
|
||||||
className,
|
classPath,
|
||||||
dayMusic,
|
dayMusic,
|
||||||
nightMusic,
|
nightMusic,
|
||||||
battleMusic,
|
battleMusic,
|
||||||
@ -62,10 +78,13 @@ namespace FFXIVClassic_Map_Server
|
|||||||
canStealth,
|
canStealth,
|
||||||
isInstanceRaid
|
isInstanceRaid
|
||||||
FROM server_zones
|
FROM server_zones
|
||||||
WHERE zoneName IS NOT NULL";
|
WHERE zoneName IS NOT NULL and serverIp = @ip and serverPort = @port";
|
||||||
|
|
||||||
MySqlCommand cmd = new MySqlCommand(query, conn);
|
MySqlCommand cmd = new MySqlCommand(query, conn);
|
||||||
|
|
||||||
|
cmd.Parameters.AddWithValue("@ip", ConfigConstants.OPTIONS_BINDIP);
|
||||||
|
cmd.Parameters.AddWithValue("@port", ConfigConstants.OPTIONS_PORT);
|
||||||
|
|
||||||
using (MySqlDataReader reader = cmd.ExecuteReader())
|
using (MySqlDataReader reader = cmd.ExecuteReader())
|
||||||
{
|
{
|
||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
@ -95,6 +114,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
id,
|
id,
|
||||||
parentZoneId,
|
parentZoneId,
|
||||||
privateAreaName,
|
privateAreaName,
|
||||||
|
privateAreaType,
|
||||||
className,
|
className,
|
||||||
dayMusic,
|
dayMusic,
|
||||||
nightMusic,
|
nightMusic,
|
||||||
@ -113,7 +133,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
if (zoneList.ContainsKey(parentZoneId))
|
if (zoneList.ContainsKey(parentZoneId))
|
||||||
{
|
{
|
||||||
Zone parent = zoneList[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);
|
parent.AddPrivateArea(privArea);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -168,7 +188,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
if (!reader.IsDBNull(7))
|
if (!reader.IsDBNull(7))
|
||||||
privArea = reader.GetString(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;
|
zoneEntranceList[id] = entance;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@ -257,12 +277,17 @@ namespace FFXIVClassic_Map_Server
|
|||||||
|
|
||||||
string query = @"
|
string query = @"
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
gamedata_actor_class.id,
|
||||||
classPath,
|
classPath,
|
||||||
displayNameId,
|
displayNameId,
|
||||||
propertyFlags,
|
propertyFlags,
|
||||||
eventConditions
|
eventConditions,
|
||||||
|
pushCommand,
|
||||||
|
pushCommandSub,
|
||||||
|
pushCommandPriority
|
||||||
FROM gamedata_actor_class
|
FROM gamedata_actor_class
|
||||||
|
LEFT JOIN gamedata_actor_pushcommand
|
||||||
|
ON gamedata_actor_class.id = gamedata_actor_pushcommand.id
|
||||||
WHERE classPath <> ''
|
WHERE classPath <> ''
|
||||||
";
|
";
|
||||||
|
|
||||||
@ -284,7 +309,18 @@ namespace FFXIVClassic_Map_Server
|
|||||||
else
|
else
|
||||||
eventConditions = "{}";
|
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);
|
actorClasses.Add(id, actorClass);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@ -334,13 +370,20 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
|
uint zoneId = reader.GetUInt32("zoneId");
|
||||||
|
uint classId = reader.GetUInt32("actorClassId");
|
||||||
|
if (!actorClasses.ContainsKey(classId))
|
||||||
|
continue;
|
||||||
|
if (!zoneList.ContainsKey(zoneId))
|
||||||
|
continue;
|
||||||
|
Zone zone = zoneList[zoneId];
|
||||||
|
if (zone == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
string customName = null;
|
string customName = null;
|
||||||
if (!reader.IsDBNull(11))
|
if (!reader.IsDBNull(11))
|
||||||
customName = reader.GetString("customDisplayName");
|
customName = reader.GetString("customDisplayName");
|
||||||
|
|
||||||
uint classId = reader.GetUInt32("actorClassId");
|
|
||||||
string uniqueId = reader.GetString("uniqueId");
|
string uniqueId = reader.GetString("uniqueId");
|
||||||
uint zoneId = reader.GetUInt32("zoneId");
|
|
||||||
string privAreaName = reader.GetString("privateAreaName");
|
string privAreaName = reader.GetString("privateAreaName");
|
||||||
uint privAreaLevel = reader.GetUInt32("privateAreaLevel");
|
uint privAreaLevel = reader.GetUInt32("privateAreaLevel");
|
||||||
float x = reader.GetFloat("positionX");
|
float x = reader.GetFloat("positionX");
|
||||||
@ -350,15 +393,6 @@ namespace FFXIVClassic_Map_Server
|
|||||||
ushort state = reader.GetUInt16("actorState");
|
ushort state = reader.GetUInt16("actorState");
|
||||||
uint animId = reader.GetUInt32("animationId");
|
uint animId = reader.GetUInt32("animationId");
|
||||||
|
|
||||||
if (!actorClasses.ContainsKey(classId))
|
|
||||||
continue;
|
|
||||||
if (!zoneList.ContainsKey(zoneId))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Zone zone = zoneList[zoneId];
|
|
||||||
if (zone == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SpawnLocation spawn = new SpawnLocation(classId, uniqueId, zoneId, privAreaName, privAreaLevel, x, y, z, rot, state, animId);
|
SpawnLocation spawn = new SpawnLocation(classId, uniqueId, zoneId, privAreaName, privAreaLevel, x, y, z, rot, state, animId);
|
||||||
|
|
||||||
zone.AddSpawnLocation(spawn);
|
zone.AddSpawnLocation(spawn);
|
||||||
@ -416,7 +450,7 @@ namespace FFXIVClassic_Map_Server
|
|||||||
|
|
||||||
player.SendMessage(0x20, "", "Doing Seamless Zone Change");
|
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.
|
//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");
|
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
|
//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];
|
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.
|
//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;
|
Area oldZone = player.zone;
|
||||||
//Remove player from currentZone if transfer else it's login
|
//Remove player from currentZone if transfer else it's login
|
||||||
if (player.zone != null)
|
if (player.zone != null)
|
||||||
@ -531,46 +583,48 @@ namespace FFXIVClassic_Map_Server
|
|||||||
oldZone.RemoveActorFromZone(player);
|
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);
|
newArea.AddActorToZone(player);
|
||||||
|
|
||||||
//Update player actor's properties
|
//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.zone = newArea;
|
||||||
player.positionX = spawnX;
|
player.positionX = spawnX;
|
||||||
player.positionY = spawnY;
|
player.positionY = spawnY;
|
||||||
player.positionZ = spawnZ;
|
player.positionZ = spawnZ;
|
||||||
player.rotation = spawnRotation;
|
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
|
//Send packets
|
||||||
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId), true, false);
|
player.playerSession.QueuePacket(DeleteAllActorsPacket.BuildPacket(player.actorId));
|
||||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x0), true, false);
|
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x2));
|
||||||
player.SendZoneInPackets(this, spawnType);
|
player.SendZoneInPackets(this, spawnType);
|
||||||
player.playerSession.ClearInstance();
|
player.playerSession.ClearInstance();
|
||||||
player.SendInstanceUpdate();
|
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
|
//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
|
//Remove player from currentZone if transfer else it's login
|
||||||
if (player.zone != null)
|
if (player.zone != null)
|
||||||
{
|
{
|
||||||
|
player.playerSession.LockUpdates(true);
|
||||||
player.zone.RemoveActorFromZone(player);
|
player.zone.RemoveActorFromZone(player);
|
||||||
player.zone.AddActorToZone(player);
|
player.zone.AddActorToZone(player);
|
||||||
|
|
||||||
@ -606,35 +661,99 @@ namespace FFXIVClassic_Map_Server
|
|||||||
player.rotation = spawnRotation;
|
player.rotation = spawnRotation;
|
||||||
|
|
||||||
//Send packets
|
//Send packets
|
||||||
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x0), true, false);
|
player.playerSession.QueuePacket(_0xE2Packet.BuildPacket(player.actorId, 0x10));
|
||||||
player.playerSession.QueuePacket(player.CreateSpawnTeleportPacket(player.actorId, spawnType), true, false);
|
player.playerSession.QueuePacket(player.CreateSpawnTeleportPacket(spawnType));
|
||||||
player.SendInstanceUpdate();
|
|
||||||
|
|
||||||
|
player.playerSession.LockUpdates(false);
|
||||||
|
player.SendInstanceUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Login Zone In
|
//Moves actor to new zone, and sends packets to spawn at the given coords.
|
||||||
public void DoLogin(Player player)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Session started, zone into world
|
||||||
|
public void DoZoneIn(Player player, bool isLogin, ushort spawnType)
|
||||||
{
|
{
|
||||||
//Add player to new zone and update
|
//Add player to new zone and update
|
||||||
Zone zone = GetZone(player.zoneId);
|
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
|
//This server does not contain that zoneId
|
||||||
if (zone == null)
|
if (playerArea == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Set the current zone and add player
|
//Set the current zone and add player
|
||||||
player.zone = zone;
|
player.zone = playerArea;
|
||||||
|
|
||||||
LuaEngine.OnBeginLogin(player);
|
playerArea.AddActorToZone(player);
|
||||||
|
|
||||||
zone.AddActorToZone(player);
|
|
||||||
|
|
||||||
//Send packets
|
//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);
|
player.SendZoneInPackets(this, spawnType);
|
||||||
LuaEngine.OnZoneIn(player);
|
|
||||||
|
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)
|
public void ReloadZone(uint zoneId)
|
||||||
@ -648,15 +767,267 @@ 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)
|
public Player GetPCInWorld(string name)
|
||||||
{
|
{
|
||||||
foreach (Zone zone in zoneList.Values)
|
if (Server.GetServer().GetSession(name) != null)
|
||||||
{
|
return Server.GetServer().GetSession(name).GetActor();
|
||||||
Player p = zone.FindPCInZone(name);
|
else
|
||||||
if (p != null)
|
return null;
|
||||||
return p;
|
}
|
||||||
}
|
|
||||||
return null;
|
public Player GetPCInWorld(uint charId)
|
||||||
|
{
|
||||||
|
if (Server.GetServer().GetSession(charId) != null)
|
||||||
|
return Server.GetServer().GetSession(charId).GetActor();
|
||||||
|
else
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Actor GetActorInWorld(uint charId)
|
public Actor GetActorInWorld(uint charId)
|
||||||
@ -670,13 +1041,13 @@ namespace FFXIVClassic_Map_Server
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player GetPCInWorld(uint charId)
|
public Actor GetActorInWorldByUniqueId(string uid)
|
||||||
{
|
{
|
||||||
foreach (Zone zone in zoneList.Values)
|
foreach (Zone zone in zoneList.Values)
|
||||||
{
|
{
|
||||||
Player p = zone.FindPCInZone(charId);
|
Actor a = zone.FindActorInZoneByUniqueID(uid);
|
||||||
if (p != null)
|
if (a != null)
|
||||||
return p;
|
return a;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -688,6 +1059,14 @@ namespace FFXIVClassic_Map_Server
|
|||||||
return zoneList[zoneId];
|
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()
|
public WorldMaster GetActor()
|
||||||
{
|
{
|
||||||
return worldMaster;
|
return worldMaster;
|
||||||
@ -702,16 +1081,18 @@ namespace FFXIVClassic_Map_Server
|
|||||||
{
|
{
|
||||||
public uint zoneId;
|
public uint zoneId;
|
||||||
public string privateAreaName;
|
public string privateAreaName;
|
||||||
|
public int privateAreaType;
|
||||||
public byte spawnType;
|
public byte spawnType;
|
||||||
public float spawnX;
|
public float spawnX;
|
||||||
public float spawnY;
|
public float spawnY;
|
||||||
public float spawnZ;
|
public float spawnZ;
|
||||||
public float spawnRotation;
|
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.zoneId = zoneId;
|
||||||
this.privateAreaName = privateAreaName;
|
this.privateAreaName = privateAreaName;
|
||||||
|
this.privateAreaType = privateAreaType;
|
||||||
this.spawnType = spawnType;
|
this.spawnType = spawnType;
|
||||||
this.spawnX = x;
|
this.spawnX = x;
|
||||||
this.spawnY = y;
|
this.spawnY = y;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic_Map_Server.actors;
|
using FFXIVClassic_Map_Server.actors;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
@ -7,6 +7,9 @@ using FFXIVClassic.Common;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FFXIVClassic_Map_Server.actors.area;
|
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
|
namespace FFXIVClassic_Map_Server.Actors
|
||||||
{
|
{
|
||||||
@ -23,9 +26,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
public float positionX, positionY, positionZ, rotation;
|
public float positionX, positionY, positionZ, rotation;
|
||||||
public float oldPositionX, oldPositionY, oldPositionZ, oldRotation;
|
public float oldPositionX, oldPositionY, oldPositionZ, oldRotation;
|
||||||
public ushort moveState, oldMoveState;
|
public ushort moveState, oldMoveState;
|
||||||
public float[] moveSpeeds = new float[5];
|
public float[] moveSpeeds = new float[4];
|
||||||
|
|
||||||
public uint zoneId, zoneId2;
|
public uint zoneId, zoneId2;
|
||||||
|
public string privateArea;
|
||||||
|
public uint privateAreaType;
|
||||||
public Area zone = null;
|
public Area zone = null;
|
||||||
public Area zone2 = null;
|
public Area zone2 = null;
|
||||||
public bool isZoning = false;
|
public bool isZoning = false;
|
||||||
@ -53,69 +58,91 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
this.moveSpeeds[0] = SetActorSpeedPacket.DEFAULT_STOP;
|
this.moveSpeeds[0] = SetActorSpeedPacket.DEFAULT_STOP;
|
||||||
this.moveSpeeds[1] = SetActorSpeedPacket.DEFAULT_WALK;
|
this.moveSpeeds[1] = SetActorSpeedPacket.DEFAULT_WALK;
|
||||||
this.moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN;
|
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;
|
SubPacket spawnPacket;
|
||||||
if (!spawnedFirstTime && playerActorId == actorId)
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
if (this is Player)
|
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
|
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;
|
spawnedFirstTime = true;
|
||||||
|
|
||||||
return spawnPacket;
|
return spawnPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubPacket CreateSpawnTeleportPacket(uint playerActorId, uint spawnType)
|
public SubPacket CreateSpawnTeleportPacket(ushort spawnType)
|
||||||
{
|
{
|
||||||
SubPacket spawnPacket;
|
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();
|
//spawnPacket.DebugPrintSubPacket();
|
||||||
|
|
||||||
return spawnPacket;
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
|
|
||||||
@ -126,126 +153,147 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
if (eventConditions.talkEventConditions != null)
|
if (eventConditions.talkEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
|
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
|
||||||
subpackets.Add(SetTalkEventCondition.BuildPacket(playerActorId, actorId, condition));
|
subpackets.Add(SetTalkEventCondition.BuildPacket(actorId, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventConditions.noticeEventConditions != null)
|
if (eventConditions.noticeEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.NoticeEventCondition condition in eventConditions.noticeEventConditions)
|
foreach (EventList.NoticeEventCondition condition in eventConditions.noticeEventConditions)
|
||||||
subpackets.Add(SetNoticeEventCondition.BuildPacket(playerActorId, actorId, condition));
|
subpackets.Add(SetNoticeEventCondition.BuildPacket(actorId, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventConditions.emoteEventConditions != null)
|
if (eventConditions.emoteEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.EmoteEventCondition condition in eventConditions.emoteEventConditions)
|
foreach (EventList.EmoteEventCondition condition in eventConditions.emoteEventConditions)
|
||||||
subpackets.Add(SetEmoteEventCondition.BuildPacket(playerActorId, actorId, condition));
|
subpackets.Add(SetEmoteEventCondition.BuildPacket(actorId, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventConditions.pushWithCircleEventConditions != null)
|
if (eventConditions.pushWithCircleEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.PushCircleEventCondition condition in eventConditions.pushWithCircleEventConditions)
|
foreach (EventList.PushCircleEventCondition condition in eventConditions.pushWithCircleEventConditions)
|
||||||
subpackets.Add(SetPushEventConditionWithCircle.BuildPacket(playerActorId, actorId, condition));
|
subpackets.Add(SetPushEventConditionWithCircle.BuildPacket(actorId, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventConditions.pushWithFanEventConditions != null)
|
if (eventConditions.pushWithFanEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.PushFanEventCondition condition in eventConditions.pushWithFanEventConditions)
|
foreach (EventList.PushFanEventCondition condition in eventConditions.pushWithFanEventConditions)
|
||||||
subpackets.Add(SetPushEventConditionWithFan.BuildPacket(playerActorId, actorId, condition));
|
subpackets.Add(SetPushEventConditionWithFan.BuildPacket(actorId, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventConditions.pushWithBoxEventConditions != null)
|
if (eventConditions.pushWithBoxEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.PushBoxEventCondition condition in eventConditions.pushWithBoxEventConditions)
|
foreach (EventList.PushBoxEventCondition condition in eventConditions.pushWithBoxEventConditions)
|
||||||
subpackets.Add(SetPushEventConditionWithTriggerBox.BuildPacket(playerActorId, actorId, condition));
|
subpackets.Add(SetPushEventConditionWithTriggerBox.BuildPacket(actorId, condition));
|
||||||
}
|
}
|
||||||
|
|
||||||
return subpackets;
|
return subpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BasePacket GetSetEventStatusPackets(uint playerActorId)
|
public List<SubPacket> GetSetEventStatusPackets()
|
||||||
{
|
{
|
||||||
List<SubPacket> subpackets = new List<SubPacket>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
|
|
||||||
//Return empty list
|
//Return empty list
|
||||||
if (eventConditions == null)
|
if (eventConditions == null)
|
||||||
return BasePacket.CreatePacket(subpackets, true, false);
|
return subpackets;
|
||||||
|
|
||||||
if (eventConditions.talkEventConditions != null)
|
if (eventConditions.talkEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.TalkEventCondition condition in eventConditions.talkEventConditions)
|
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)
|
if (eventConditions.noticeEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.NoticeEventCondition condition in eventConditions.noticeEventConditions)
|
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)
|
if (eventConditions.emoteEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.EmoteEventCondition condition in eventConditions.emoteEventConditions)
|
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)
|
if (eventConditions.pushWithCircleEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.PushCircleEventCondition condition in eventConditions.pushWithCircleEventConditions)
|
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)
|
if (eventConditions.pushWithFanEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.PushFanEventCondition condition in eventConditions.pushWithFanEventConditions)
|
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)
|
if (eventConditions.pushWithBoxEventConditions != null)
|
||||||
{
|
{
|
||||||
foreach (EventList.PushBoxEventCondition condition in eventConditions.pushWithBoxEventConditions)
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
subpackets.Add(CreateAddActorPacket(playerActorId, 8));
|
subpackets.Add(CreateAddActorPacket(8));
|
||||||
subpackets.AddRange(GetEventConditionPackets(playerActorId));
|
subpackets.AddRange(GetEventConditionPackets());
|
||||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
subpackets.Add(CreateSpeedPacket());
|
||||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, spawnType));
|
subpackets.Add(CreateSpawnPositonPacket(player, spawnType));
|
||||||
subpackets.Add(CreateNamePacket(playerActorId));
|
subpackets.Add(CreateNamePacket());
|
||||||
subpackets.Add(CreateStatePacket(playerActorId));
|
subpackets.Add(CreateStatePacket());
|
||||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
subpackets.Add(CreateIsZoneingPacket());
|
||||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
subpackets.Add(CreateScriptBindPacket(player));
|
||||||
return BasePacket.CreatePacket(subpackets, true, false);
|
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");
|
SetActorPropetyPacket initProperties = new SetActorPropetyPacket("/_init");
|
||||||
initProperties.AddByte(0xE14B0CA8, 1);
|
initProperties.AddByte(0xE14B0CA8, 1);
|
||||||
initProperties.AddByte(0x2138FD71, 1);
|
initProperties.AddByte(0x2138FD71, 1);
|
||||||
initProperties.AddByte(0xFBFBCFB1, 1);
|
initProperties.AddByte(0xFBFBCFB1, 1);
|
||||||
initProperties.AddTarget();
|
initProperties.AddTarget();
|
||||||
return BasePacket.CreatePacket(initProperties.BuildPacket(playerActorId, actorId), true, false);
|
packets.Add(initProperties.BuildPacket(actorId));
|
||||||
|
return packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(Object obj)
|
public override bool Equals(Object obj)
|
||||||
@ -280,8 +328,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
public void ChangeState(ushort newState)
|
public void ChangeState(ushort newState)
|
||||||
{
|
{
|
||||||
currentMainState = newState;
|
currentMainState = newState;
|
||||||
SubPacket ChangeStatePacket = SetActorStatePacket.BuildPacket(actorId, actorId, newState, currentSubState);
|
SubPacket ChangeStatePacket = SetActorStatePacket.BuildPacket(actorId, newState, currentSubState);
|
||||||
SubPacket battleActionPacket = BattleAction1Packet.BuildPacket(actorId, actorId);
|
SubPacket battleActionPacket = BattleActionX01Packet.BuildPacket(actorId, actorId, actorId, 0x72000062, 1, 0, 0x05209, 0, 0);
|
||||||
zone.BroadcastPacketAroundActor(this, ChangeStatePacket);
|
zone.BroadcastPacketAroundActor(this, ChangeStatePacket);
|
||||||
zone.BroadcastPacketAroundActor(this, battleActionPacket);
|
zone.BroadcastPacketAroundActor(this, battleActionPacket);
|
||||||
}
|
}
|
||||||
@ -289,20 +337,24 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
public void ChangeSpeed(int type, float value)
|
public void ChangeSpeed(int type, float value)
|
||||||
{
|
{
|
||||||
moveSpeeds[type] = 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);
|
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[0] = speedStop;
|
||||||
moveSpeeds[1] = speedWalk;
|
moveSpeeds[1] = speedWalk;
|
||||||
moveSpeeds[2] = speedRun;
|
moveSpeeds[2] = speedRun;
|
||||||
moveSpeeds[3] = speedRun;
|
moveSpeeds[3] = speedActive;
|
||||||
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);
|
zone.BroadcastPacketAroundActor(this, ChangeSpeedPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Update(double deltaTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void GenerateActorName(int actorNumber)
|
public void GenerateActorName(int actorNumber)
|
||||||
{
|
{
|
||||||
//Format Class Name
|
//Format Class Name
|
||||||
@ -345,11 +397,92 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
uint zoneId = zone.actorId;
|
uint zoneId = zone.actorId;
|
||||||
uint privLevel = 0;
|
uint privLevel = 0;
|
||||||
if (zone is PrivateArea)
|
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);
|
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()
|
public List<float> GetPos()
|
||||||
{
|
{
|
||||||
List<float> pos = new List<float>();
|
List<float> pos = new List<float>();
|
||||||
@ -376,7 +509,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
rotation = rot;
|
rotation = rot;
|
||||||
|
|
||||||
// todo: handle zone?
|
// 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()
|
public Area GetZone()
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using FFXIVClassic_Map_Server;
|
using FFXIVClassic_Map_Server;
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic_Map_Server.actors.area;
|
using FFXIVClassic_Map_Server.actors.area;
|
||||||
using FFXIVClassic_Map_Server.actors.chara.npc;
|
using FFXIVClassic_Map_Server.actors.chara.npc;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
@ -14,6 +13,8 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FFXIVClassic_Map_Server.packets.send;
|
using FFXIVClassic_Map_Server.packets.send;
|
||||||
|
using FFXIVClassic_Map_Server.actors.group;
|
||||||
|
using FFXIVClassic_Map_Server.actors.director;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.Actors
|
namespace FFXIVClassic_Map_Server.Actors
|
||||||
{
|
{
|
||||||
@ -28,17 +29,23 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
protected string classPath;
|
protected string classPath;
|
||||||
|
|
||||||
public int boundingGridSize = 50;
|
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 numXBlocks, numYBlocks;
|
||||||
protected int halfWidth, halfHeight;
|
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 List<SpawnLocation> mSpawnLocations = new List<SpawnLocation>();
|
||||||
protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>();
|
protected Dictionary<uint, Actor> mActorList = new Dictionary<uint, Actor>();
|
||||||
protected List<Actor>[,] mActorBlock;
|
protected List<Actor>[,] mActorBlock;
|
||||||
|
|
||||||
LuaScript areaScript;
|
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)
|
: base(id)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -56,9 +63,10 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
this.displayNameId = 0;
|
this.displayNameId = 0;
|
||||||
this.customDisplayName = "_areaMaster";
|
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;
|
numXBlocks = (maxX - minX) / boundingGridSize;
|
||||||
numYBlocks = (maxY - minY) / boundingGridSize;
|
numYBlocks = (maxY - minY) / boundingGridSize;
|
||||||
@ -68,40 +76,42 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
for (int y = 0; y < numYBlocks; y++)
|
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>();
|
mActorBlock[x, y] = new List<Actor>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
public override SubPacket CreateScriptBindPacket()
|
||||||
{
|
{
|
||||||
List<LuaParam> lParams;
|
List<LuaParam> lParams;
|
||||||
lParams = LuaUtils.CreateLuaParamList(classPath, false, true, zoneName, "/Area/Zone/ZoneDefault", -1, (byte)1, true, false, false, false, false, false, false, false);
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
subpackets.Add(CreateAddActorPacket(0));
|
||||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
subpackets.Add(CreateSpeedPacket());
|
||||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||||
subpackets.Add(CreateNamePacket(playerActorId));
|
subpackets.Add(CreateNamePacket());
|
||||||
subpackets.Add(CreateStatePacket(playerActorId));
|
subpackets.Add(CreateStatePacket());
|
||||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
subpackets.Add(CreateIsZoneingPacket());
|
||||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
subpackets.Add(CreateScriptBindPacket());
|
||||||
return BasePacket.CreatePacket(subpackets, true, false);
|
return subpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Actor Management
|
#region Actor Management
|
||||||
|
|
||||||
public void AddActorToZone(Actor actor)
|
public void AddActorToZone(Actor actor)
|
||||||
{
|
{
|
||||||
if (!mActorList.ContainsKey(actor.actorId))
|
lock (mActorList)
|
||||||
mActorList.Add(actor.actorId, actor);
|
{
|
||||||
|
if (!mActorList.ContainsKey(actor.actorId))
|
||||||
|
mActorList.Add(actor.actorId, actor);
|
||||||
|
}
|
||||||
|
|
||||||
int gridX = (int)actor.positionX / boundingGridSize;
|
int gridX = (int)actor.positionX / boundingGridSize;
|
||||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||||
@ -125,7 +135,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
public void RemoveActorFromZone(Actor actor)
|
public void RemoveActorFromZone(Actor actor)
|
||||||
{
|
{
|
||||||
mActorList.Remove(actor.actorId);
|
lock (mActorList)
|
||||||
|
mActorList.Remove(actor.actorId);
|
||||||
|
|
||||||
int gridX = (int)actor.positionX / boundingGridSize;
|
int gridX = (int)actor.positionX / boundingGridSize;
|
||||||
int gridY = (int)actor.positionZ / boundingGridSize;
|
int gridY = (int)actor.positionZ / boundingGridSize;
|
||||||
@ -214,11 +225,14 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
List<Actor> result = new List<Actor>();
|
List<Actor> result = new List<Actor>();
|
||||||
|
|
||||||
for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++)
|
lock (mActorBlock)
|
||||||
{
|
{
|
||||||
for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++)
|
for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++)
|
||||||
{
|
{
|
||||||
result.AddRange(mActorBlock[gx, gy]);
|
for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++)
|
||||||
|
{
|
||||||
|
result.AddRange(mActorBlock[gx, gy]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,11 +271,14 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
List<Actor> result = new List<Actor>();
|
List<Actor> result = new List<Actor>();
|
||||||
|
|
||||||
for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++)
|
lock (mActorBlock)
|
||||||
{
|
{
|
||||||
for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++)
|
for (int gy = ((gridY - checkDistance) < 0 ? 0 : (gridY - checkDistance)); gy <= ((gridY + checkDistance) >= numYBlocks ? numYBlocks - 1 : (gridY + checkDistance)); gy++)
|
||||||
{
|
{
|
||||||
result.AddRange(mActorBlock[gx, gy]);
|
for (int gx = ((gridX - checkDistance) < 0 ? 0 : (gridX - checkDistance)); gx <= ((gridX + checkDistance) >= numXBlocks ? numXBlocks - 1 : (gridX + checkDistance)); gx++)
|
||||||
|
{
|
||||||
|
result.AddRange(mActorBlock[gx, gy]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,46 +297,83 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public Actor FindActorInZone(uint id)
|
public Actor FindActorInArea(uint id)
|
||||||
{
|
{
|
||||||
if (!mActorList.ContainsKey(id))
|
lock (mActorList)
|
||||||
return null;
|
{
|
||||||
return mActorList[id];
|
if (!mActorList.ContainsKey(id))
|
||||||
|
return null;
|
||||||
|
return mActorList[id];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player FindPCInZone(string name)
|
public Actor FindActorInZoneByUniqueID(string uniqueId)
|
||||||
{
|
{
|
||||||
foreach (Actor a in mActorList.Values)
|
lock (mActorList)
|
||||||
{
|
{
|
||||||
if (a is Player)
|
foreach (Actor a in mActorList.Values)
|
||||||
{
|
{
|
||||||
if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower()))
|
if (a is Npc)
|
||||||
return (Player)a;
|
{
|
||||||
|
if (((Npc)a).GetUniqueId().ToLower().Equals(uniqueId))
|
||||||
|
return a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Player FindPCInZone(string name)
|
||||||
|
{
|
||||||
|
lock (mActorList)
|
||||||
|
{
|
||||||
|
foreach (Actor a in mActorList.Values)
|
||||||
|
{
|
||||||
|
if (a is Player)
|
||||||
|
{
|
||||||
|
if (((Player)a).customDisplayName.ToLower().Equals(name.ToLower()))
|
||||||
|
return (Player)a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Player FindPCInZone(uint id)
|
public Player FindPCInZone(uint id)
|
||||||
{
|
{
|
||||||
if (!mActorList.ContainsKey(id))
|
lock (mActorList)
|
||||||
return null;
|
{
|
||||||
return (Player)mActorList[id];
|
if (!mActorList.ContainsKey(id))
|
||||||
|
return null;
|
||||||
|
return (Player)mActorList[id];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
//Clear All
|
lock (mActorList)
|
||||||
mActorList.Clear();
|
|
||||||
for (int y = 0; y < numYBlocks; y++)
|
|
||||||
{
|
{
|
||||||
for (int x = 0; x < numXBlocks; x++)
|
//Clear All
|
||||||
|
mActorList.Clear();
|
||||||
|
lock (mActorBlock)
|
||||||
{
|
{
|
||||||
mActorBlock[x, y].Clear();
|
for (int y = 0; y < numYBlocks; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < numXBlocks; x++)
|
||||||
|
{
|
||||||
|
mActorBlock[x, y].Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BroadcastPacketsAroundActor(Actor actor, List<SubPacket> packets)
|
||||||
|
{
|
||||||
|
foreach (SubPacket packet in packets)
|
||||||
|
BroadcastPacketAroundActor(actor, packet);
|
||||||
|
}
|
||||||
|
|
||||||
public void BroadcastPacketAroundActor(Actor actor, SubPacket packet)
|
public void BroadcastPacketAroundActor(Actor actor, SubPacket packet)
|
||||||
{
|
{
|
||||||
if (isIsolated)
|
if (isIsolated)
|
||||||
@ -333,7 +387,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
if (isIsolated && packet.header.sourceId != a.actorId)
|
if (isIsolated && packet.header.sourceId != a.actorId)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SubPacket clonedPacket = new SubPacket(packet, actor.actorId);
|
SubPacket clonedPacket = new SubPacket(packet, a.actorId);
|
||||||
Player p = (Player)a;
|
Player p = (Player)a;
|
||||||
p.QueuePacket(clonedPacket);
|
p.QueuePacket(clonedPacket);
|
||||||
}
|
}
|
||||||
@ -347,31 +401,192 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
if (actorClass == null)
|
if (actorClass == null)
|
||||||
return;
|
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);
|
npc.LoadEventConditions(actorClass.eventConditions);
|
||||||
|
|
||||||
AddActorToZone(npc);
|
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)
|
public void ChangeWeather(ushort weather, ushort transitionTime, Player player, bool zoneWide = false)
|
||||||
{
|
{
|
||||||
weatherNormal = weather;
|
weatherNormal = weather;
|
||||||
|
|
||||||
if (player != null && !zoneWide)
|
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)
|
if (zoneWide)
|
||||||
{
|
{
|
||||||
foreach (var actor in mActorList)
|
lock (mActorList)
|
||||||
{
|
{
|
||||||
if (actor.Value is Player)
|
foreach (var actor in mActorList)
|
||||||
{
|
{
|
||||||
player = ((Player)actor.Value);
|
if (actor.Value is Player)
|
||||||
player.QueuePacket(BasePacket.CreatePacket(SetWeatherPacket.BuildPacket(player.actorId, weather, transitionTime), true, false));
|
{
|
||||||
|
player = ((Player)actor.Value);
|
||||||
|
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.Actors;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
@ -14,14 +15,15 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||||||
{
|
{
|
||||||
private Zone parentZone;
|
private Zone parentZone;
|
||||||
private string privateAreaName;
|
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)
|
public PrivateArea(Zone parent, uint id, string classPath, string privateAreaName, uint privateAreaType, 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)
|
: base(id, parent.zoneName, parent.regionId, classPath, bgmDay, bgmNight, bgmBattle, parent.isIsolated, parent.isInn, parent.canRideChocobo, parent.canStealth, true)
|
||||||
{
|
{
|
||||||
this.parentZone = parent;
|
this.parentZone = parent;
|
||||||
|
this.zoneName = parent.zoneName;
|
||||||
this.privateAreaName = privateAreaName;
|
this.privateAreaName = privateAreaName;
|
||||||
this.privateAreaLevel = privateAreaLevel;
|
this.privateAreaType = privateAreaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetPrivateAreaName()
|
public string GetPrivateAreaName()
|
||||||
@ -29,9 +31,9 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||||||
return privateAreaName;
|
return privateAreaName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetPrivateAreaLevel()
|
public uint GetPrivateAreaType()
|
||||||
{
|
{
|
||||||
return privateAreaLevel;
|
return privateAreaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Zone GetParentZone()
|
public Zone GetParentZone()
|
||||||
@ -39,18 +41,17 @@ namespace FFXIVClassic_Map_Server.actors.area
|
|||||||
return parentZone;
|
return parentZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
public override SubPacket CreateScriptBindPacket()
|
||||||
{
|
{
|
||||||
List<LuaParam> lParams;
|
List<LuaParam> lParams;
|
||||||
|
|
||||||
string path = className;
|
string path = className;
|
||||||
|
|
||||||
if (className.ToLower().Contains("content"))
|
string realClassName = className.Substring(className.LastIndexOf("/") + 1);
|
||||||
path = "Content/" + className;
|
|
||||||
|
|
||||||
lParams = LuaUtils.CreateLuaParamList("/Area/PrivateArea/" + path, false, true, zoneName, privateAreaName, 0x9E, canRideChocobo ? (byte)1 : (byte)0, canStealth, isInn, false, false, false, false, false, false);
|
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, playerActorId, actorName, className, lParams).DebugPrintSubPacket();
|
ActorInstantiatePacket.BuildPacket(actorId, actorName, realClassName, lParams).DebugPrintSubPacket();
|
||||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
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_Map_Server;
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic_Map_Server.actors.chara.npc;
|
using FFXIVClassic_Map_Server.actors.chara.npc;
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
@ -10,15 +10,18 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using FFXIVClassic_Map_Server.actors.director;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.actors.area
|
namespace FFXIVClassic_Map_Server.actors.area
|
||||||
{
|
{
|
||||||
class Zone : Area
|
class Zone : Area
|
||||||
{
|
{
|
||||||
Dictionary<string, Dictionary<uint, PrivateArea>> privateAreas = new Dictionary<string, Dictionary<uint, PrivateArea>>();
|
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)
|
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, className, bgmDay, bgmNight, bgmBattle, isIsolated, isInn, canRideChocobo, canStealth, 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)
|
public void AddPrivateArea(PrivateArea pa)
|
||||||
{
|
{
|
||||||
if (privateAreas.ContainsKey(pa.GetPrivateAreaName()))
|
if (privateAreas.ContainsKey(pa.GetPrivateAreaName()))
|
||||||
privateAreas[pa.GetPrivateAreaName()][0] = pa;
|
privateAreas[pa.GetPrivateAreaName()][pa.GetPrivateAreaType()] = pa;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
privateAreas[pa.GetPrivateAreaName()] = new Dictionary<uint, PrivateArea>();
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
public override SubPacket CreateScriptBindPacket()
|
||||||
{
|
{
|
||||||
bool isEntranceDesion = false;
|
bool isEntranceDesion = false;
|
||||||
|
|
||||||
List<LuaParam> lParams;
|
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);
|
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, playerActorId, actorName, className, lParams);
|
return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSpawnLocation(SpawnLocation spawn)
|
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.Actors.Chara;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
|
using FFXIVClassic_Map_Server.utils;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.Actors
|
namespace FFXIVClassic_Map_Server.Actors
|
||||||
{
|
{
|
||||||
@ -35,6 +38,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
public const int L_INDEXFINGER = 26;
|
public const int L_INDEXFINGER = 26;
|
||||||
public const int UNKNOWN = 27;
|
public const int UNKNOWN = 27;
|
||||||
|
|
||||||
|
public bool isStatic = false;
|
||||||
|
|
||||||
public uint modelId;
|
public uint modelId;
|
||||||
public uint[] appearanceIds = new uint[28];
|
public uint[] appearanceIds = new uint[28];
|
||||||
|
|
||||||
@ -48,6 +53,9 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
public Work work = new Work();
|
public Work work = new Work();
|
||||||
public CharaWork charaWork = new CharaWork();
|
public CharaWork charaWork = new CharaWork();
|
||||||
|
|
||||||
|
public Group currentParty = null;
|
||||||
|
public ContentGroup currentContentGroup = null;
|
||||||
|
|
||||||
public Character(uint actorID) : base(actorID)
|
public Character(uint actorID) : base(actorID)
|
||||||
{
|
{
|
||||||
//Init timer array to "notimer"
|
//Init timer array to "notimer"
|
||||||
@ -55,30 +63,56 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
charaWork.statusShownTime[i] = 0xFFFFFFFF;
|
charaWork.statusShownTime[i] = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubPacket CreateAppearancePacket(uint playerActorId)
|
public SubPacket CreateAppearancePacket()
|
||||||
{
|
{
|
||||||
SetActorAppearancePacket setappearance = new SetActorAppearancePacket(modelId, appearanceIds);
|
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)
|
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 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 uint propertyFlags;
|
||||||
public readonly string eventConditions;
|
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.actorClassId = id;
|
||||||
this.classPath = classPath;
|
this.classPath = classPath;
|
||||||
this.displayNameId = nameId;
|
this.displayNameId = nameId;
|
||||||
this.propertyFlags = propertyFlags;
|
this.propertyFlags = propertyFlags;
|
||||||
this.eventConditions = eventConditions;
|
this.eventConditions = eventConditions;
|
||||||
|
|
||||||
|
this.pushCommand = pushCommand;
|
||||||
|
this.pushCommandSub = pushCommandSub;
|
||||||
|
this.pushCommandPriority = pushCommandPriority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.actors;
|
using FFXIVClassic_Map_Server.actors;
|
||||||
|
using FFXIVClassic_Map_Server.actors.area;
|
||||||
using FFXIVClassic_Map_Server.actors.chara.npc;
|
using FFXIVClassic_Map_Server.actors.chara.npc;
|
||||||
using FFXIVClassic_Map_Server.Actors.Chara;
|
using FFXIVClassic_Map_Server.Actors.Chara;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic_Map_Server.packets.receive.events;
|
using FFXIVClassic_Map_Server.packets.receive.events;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
using FFXIVClassic_Map_Server.utils;
|
using FFXIVClassic_Map_Server.utils;
|
||||||
@ -25,15 +25,19 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
private uint actorClassId;
|
private uint actorClassId;
|
||||||
private string uniqueIdentifier;
|
private string uniqueIdentifier;
|
||||||
|
|
||||||
|
private bool isMapObj = false;
|
||||||
|
private uint layout, instance;
|
||||||
|
|
||||||
public NpcWork npcWork = new NpcWork();
|
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)
|
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 | zoneId << 19 | (uint)actorNumber))
|
: base((4 << 28 | spawnedArea.actorId << 19 | (uint)actorNumber))
|
||||||
{
|
{
|
||||||
this.positionX = posX;
|
this.positionX = posX;
|
||||||
this.positionY = posY;
|
this.positionY = posY;
|
||||||
this.positionZ = posZ;
|
this.positionZ = posZ;
|
||||||
this.rotation = rot;
|
this.rotation = rot;
|
||||||
|
this.currentMainState = actorState;
|
||||||
this.animationId = animationId;
|
this.animationId = animationId;
|
||||||
|
|
||||||
this.displayNameId = actorClass.displayNameId;
|
this.displayNameId = actorClass.displayNameId;
|
||||||
@ -41,8 +45,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
this.uniqueIdentifier = uniqueId;
|
this.uniqueIdentifier = uniqueId;
|
||||||
|
|
||||||
this.zoneId = zoneId;
|
this.zoneId = spawnedArea.actorId;
|
||||||
this.zone = Server.GetWorldManager().GetZone(zoneId);
|
this.zone = spawnedArea;
|
||||||
|
|
||||||
this.actorClassId = actorClass.actorClassId;
|
this.actorClassId = actorClass.actorClassId;
|
||||||
|
|
||||||
@ -63,38 +67,93 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
for (int i = 0; i < 32; i++ )
|
for (int i = 0; i < 32; i++ )
|
||||||
charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1);
|
charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1);
|
||||||
|
|
||||||
if (className.Equals("JellyfishScenarioLimsaLv00"))
|
npcWork.pushCommand = actorClass.pushCommand;
|
||||||
{
|
npcWork.pushCommandSub = actorClass.pushCommandSub;
|
||||||
charaWork.property[2] = 1;
|
npcWork.pushCommandPriority = actorClass.pushCommandPriority;
|
||||||
npcWork.hateType = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
npcWork.pushCommand = 0x271D;
|
if (actorClassId == 1080078 || actorClassId == 1080079 || actorClassId == 1080080 || (actorClassId >= 1080123 && actorClassId <= 1080135) || (actorClassId >= 5000001 && actorClassId <= 5000090) || (actorClassId >= 5900001 && actorClassId <= 5900038))
|
||||||
npcWork.pushCommandPriority = 1;
|
{
|
||||||
|
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);
|
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
|
// 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;
|
List<LuaParam> lParams;
|
||||||
|
|
||||||
Player player = Server.GetWorldManager().GetPCInWorld(playerActorId);
|
lParams = LuaEngine.GetInstance().CallLuaFunctionForReturn(player, this, "init", false);
|
||||||
lParams = DoActorInit(player);
|
|
||||||
|
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)
|
if (lParams == null)
|
||||||
{
|
{
|
||||||
string classPathFake = "/Chara/Npc/Populace/PopulaceStandard";
|
string classPathFake = "/Chara/Npc/Populace/PopulaceStandard";
|
||||||
string classNameFake = "PopulaceStandard";
|
string classNameFake = "PopulaceStandard";
|
||||||
lParams = LuaUtils.CreateLuaParamList(classPathFake, false, false, false, false, false, 0xF47F6, false, false, 0, 0);
|
lParams = LuaUtils.CreateLuaParamList(classPathFake, false, false, false, false, false, 0xF47F6, false, false, 0, 0);
|
||||||
//ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams).DebugPrintSubPacket();
|
isStatic = true;
|
||||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, classNameFake, lParams);
|
//ActorInstantiatePacket.BuildPacket(actorId, actorName, classNameFake, lParams).DebugPrintSubPacket();
|
||||||
|
return ActorInstantiatePacket.BuildPacket(actorId, actorName, classNameFake, lParams);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -107,32 +166,40 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
lParams.Insert(6, new LuaParam(0, (int)actorClassId));
|
lParams.Insert(6, new LuaParam(0, (int)actorClassId));
|
||||||
}
|
}
|
||||||
|
|
||||||
//ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams).DebugPrintSubPacket();
|
//ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams).DebugPrintSubPacket();
|
||||||
return ActorInstantiatePacket.BuildPacket(actorId, playerActorId, actorName, className, lParams);
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
subpackets.Add(CreateAddActorPacket(playerActorId));
|
subpackets.Add(CreateAddActorPacket());
|
||||||
subpackets.AddRange(GetEventConditionPackets(playerActorId));
|
subpackets.AddRange(GetEventConditionPackets());
|
||||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
subpackets.Add(CreateSpeedPacket());
|
||||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x0));
|
subpackets.Add(CreateSpawnPositonPacket(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));
|
|
||||||
|
|
||||||
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
|
//Properties
|
||||||
for (int i = 0; i < charaWork.property.Length; i++)
|
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.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()
|
public string GetUniqueId()
|
||||||
@ -190,6 +263,12 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
return actorClassId;
|
return actorClassId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ChangeNpcAppearance(uint id)
|
||||||
|
{
|
||||||
|
LoadNpcAppearance(id);
|
||||||
|
zone.BroadcastPacketAroundActor(this, CreateAppearancePacket());
|
||||||
|
}
|
||||||
|
|
||||||
public void LoadNpcAppearance(uint id)
|
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)))
|
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;
|
this.eventConditions = conditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LuaParam> DoActorInit(Player player)
|
public void DoOnActorSpawn(Player player)
|
||||||
{
|
{
|
||||||
LuaScript parent = null, child = null;
|
LuaEngine.GetInstance().CallLuaFunction(player, this, "onSpawn", true);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
LuaEngine.SendError(player, String.Format("ERROR: Could not find script for actor {0}.", GetName()));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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 Despawn()
|
||||||
{
|
{
|
||||||
LuaScript parent = null, child = null;
|
zone.DespawnActor(this);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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)
|
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)
|
|
||||||
{
|
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//A party member list packet came, set the party
|
||||||
|
/* public void SetParty(MonsterPartyGroup group)
|
||||||
|
{
|
||||||
|
if (group is MonsterPartyGroup)
|
||||||
|
currentParty = group;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
{
|
{
|
||||||
class NpcWork
|
class NpcWork
|
||||||
{
|
{
|
||||||
public short pushCommand;
|
public ushort pushCommand;
|
||||||
public int pushCommandSub;
|
public int pushCommandSub;
|
||||||
public byte pushCommandPriority;
|
public byte pushCommandPriority;
|
||||||
public byte hateType;
|
public byte hateType = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
|
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
|
||||||
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.actors.chara.player
|
namespace FFXIVClassic_Map_Server.actors.chara.player
|
||||||
@ -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;
|
int currentIndex = 0;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (items.Count - currentIndex >= 16)
|
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)
|
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)
|
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++;
|
currentIndex++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
toPlayer.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId, toPlayer.actorId));
|
toPlayer.QueuePacket(InventorySetEndPacket.BuildPacket(owner.actorId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendFullEquipment(bool DoClear)
|
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.Actors;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
|
using FFXIVClassic_Map_Server.packets.send.actor.inventory;
|
||||||
using FFXIVClassic_Map_Server.packets.send.Actor.inventory;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -102,7 +102,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||||||
if (!IsSpaceForAdd(itemId, quantity))
|
if (!IsSpaceForAdd(itemId, quantity))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Item gItem = Server.GetItemGamedata(itemId);
|
ItemData gItem = Server.GetItemGamedata(itemId);
|
||||||
List<ushort> slotsToUpdate = new List<ushort>();
|
List<ushort> slotsToUpdate = new List<ushort>();
|
||||||
List<SubPacket> addItemPackets = new List<SubPacket>();
|
List<SubPacket> addItemPackets = new List<SubPacket>();
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||||||
//New item that spilled over
|
//New item that spilled over
|
||||||
for (int i = 0; i < itemId.Length; i++)
|
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);
|
InventoryItem addedItem = Database.AddItem(owner, itemId[i], 1, (byte)1, gItem.isExclusive ? (byte)0x3 : (byte)0x0, gItem.durability, inventoryCode);
|
||||||
list.Add(addedItem);
|
list.Add(addedItem);
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||||||
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
|
owner.QueuePacket(InventoryEndChangePacket.BuildPacket(owner.actorId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveItem(ulong itemDBId)
|
public void RemoveItemByUniqueId(ulong itemDBId)
|
||||||
{
|
{
|
||||||
ushort slot = 0;
|
ushort slot = 0;
|
||||||
InventoryItem toDelete = null;
|
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)
|
if (slot >= list.Count)
|
||||||
return;
|
return;
|
||||||
@ -467,7 +467,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.player
|
|||||||
for (int i = 0; i < list.Count; i++)
|
for (int i = 0; i < list.Count; i++)
|
||||||
{
|
{
|
||||||
InventoryItem item = list[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)
|
if (item.itemId == itemId && item.quantity < gItem.maxStack)
|
||||||
{
|
{
|
||||||
quantityCount -= (gItem.maxStack - item.quantity);
|
quantityCount -= (gItem.maxStack - item.quantity);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
public bool isContentsCommand;
|
public bool isContentsCommand;
|
||||||
|
|
||||||
public int castCommandClient;
|
public uint castCommandClient;
|
||||||
public int castEndClient;
|
public uint castEndClient;
|
||||||
|
|
||||||
public int[] comboNextCommandId = new int[2];
|
public int[] comboNextCommandId = new int[2];
|
||||||
public float comboCostBonusRate;
|
public float comboCostBonusRate;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using FFXIVClassic_Map_Server.packets;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -18,24 +18,24 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
this.className = "Debug";
|
this.className = "Debug";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
public override SubPacket CreateScriptBindPacket()
|
||||||
{
|
{
|
||||||
List<LuaParam> lParams;
|
List<LuaParam> lParams;
|
||||||
lParams = LuaUtils.CreateLuaParamList("/System/Debug.prog", false, false, false, false, true, 0xC51F, true, true);
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
subpackets.Add(CreateAddActorPacket(0));
|
||||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
subpackets.Add(CreateSpeedPacket());
|
||||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||||
subpackets.Add(CreateNamePacket(playerActorId));
|
subpackets.Add(CreateNamePacket());
|
||||||
subpackets.Add(CreateStatePacket(playerActorId));
|
subpackets.Add(CreateStatePacket());
|
||||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
subpackets.Add(CreateIsZoneingPacket());
|
||||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
subpackets.Add(CreateScriptBindPacket());
|
||||||
return BasePacket.CreatePacket(subpackets, true, false);
|
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.Actors;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
|
using MoonSharp.Interpreter;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.actors.director
|
namespace FFXIVClassic_Map_Server.actors.director
|
||||||
{
|
{
|
||||||
class Director : Actor
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
subpackets.Add(CreateAddActorPacket(0));
|
||||||
subpackets.AddRange(GetEventConditionPackets(playerActorId));
|
subpackets.AddRange(GetEventConditionPackets());
|
||||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
subpackets.Add(CreateSpeedPacket());
|
||||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0));
|
subpackets.Add(CreateSpawnPositonPacket(0));
|
||||||
subpackets.Add(CreateNamePacket(playerActorId));
|
subpackets.Add(CreateNamePacket());
|
||||||
subpackets.Add(CreateStatePacket(playerActorId));
|
subpackets.Add(CreateStatePacket());
|
||||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
subpackets.Add(CreateIsZoneingPacket());
|
||||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
subpackets.Add(CreateScriptBindPacket());
|
||||||
return BasePacket.CreatePacket(subpackets, true, false);
|
return subpackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BasePacket GetInitPackets(uint playerActorId)
|
public override List<SubPacket> GetInitPackets()
|
||||||
{
|
{
|
||||||
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
SetActorPropetyPacket initProperties = new SetActorPropetyPacket("/_init");
|
SetActorPropetyPacket initProperties = new SetActorPropetyPacket("/_init");
|
||||||
initProperties.AddTarget();
|
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.Common;
|
||||||
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -8,7 +9,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
class Quest : Actor
|
class Quest : Actor
|
||||||
{
|
{
|
||||||
private Player owner;
|
private Player owner;
|
||||||
private int currentPhase = 0;
|
private uint currentPhase = 0;
|
||||||
private uint questFlags = 0;
|
private uint questFlags = 0;
|
||||||
private Dictionary<string, Object> questData = new Dictionary<string, object>();
|
private Dictionary<string, Object> questData = new Dictionary<string, object>();
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
actorName = name;
|
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)
|
: base(actorID)
|
||||||
{
|
{
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
@ -32,6 +33,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
|
|
||||||
if (questData == null)
|
if (questData == null)
|
||||||
questData = new Dictionary<string, object>();
|
questData = new Dictionary<string, object>();
|
||||||
|
|
||||||
|
this.currentPhase = currentPhase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetQuestData(string dataName, object data)
|
public void SetQuestData(string dataName, object data)
|
||||||
@ -41,6 +44,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
//Inform update
|
//Inform update
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint GetQuestId()
|
||||||
|
{
|
||||||
|
return actorId & 0xFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
public object GetQuestData(string dataName)
|
public object GetQuestData(string dataName)
|
||||||
{
|
{
|
||||||
if (questData.ContainsKey(dataName))
|
if (questData.ContainsKey(dataName))
|
||||||
@ -54,11 +62,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
questData.Clear();
|
questData.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint GetQuestId()
|
|
||||||
{
|
|
||||||
return actorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearQuestFlags()
|
public void ClearQuestFlags()
|
||||||
{
|
{
|
||||||
questFlags = 0;
|
questFlags = 0;
|
||||||
@ -79,7 +82,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
else
|
else
|
||||||
questFlags &= (uint)~(1 << bitIndex);
|
questFlags &= (uint)~(1 << bitIndex);
|
||||||
|
|
||||||
//Inform update
|
DoCompletionCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetQuestFlag(int bitIndex)
|
public bool GetQuestFlag(int bitIndex)
|
||||||
@ -93,14 +96,18 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
return (questFlags & (1 << bitIndex)) == (1 << bitIndex);
|
return (questFlags & (1 << bitIndex)) == (1 << bitIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetPhase()
|
public uint GetPhase()
|
||||||
{
|
{
|
||||||
return currentPhase;
|
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()
|
public uint GetQuestFlags()
|
||||||
@ -118,5 +125,21 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
Database.SaveQuest(owner, this);
|
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.lua;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -16,24 +17,24 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
this.className = "WorldMaster";
|
this.className = "WorldMaster";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SubPacket CreateScriptBindPacket(uint playerActorId)
|
public override SubPacket CreateScriptBindPacket()
|
||||||
{
|
{
|
||||||
List<LuaParam> lParams;
|
List<LuaParam> lParams;
|
||||||
lParams = LuaUtils.CreateLuaParamList("/World/WorldMaster_event", false, false, false, false, false, null);
|
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>();
|
List<SubPacket> subpackets = new List<SubPacket>();
|
||||||
subpackets.Add(CreateAddActorPacket(playerActorId, 0));
|
subpackets.Add(CreateAddActorPacket(0));
|
||||||
subpackets.Add(CreateSpeedPacket(playerActorId));
|
subpackets.Add(CreateSpeedPacket());
|
||||||
subpackets.Add(CreateSpawnPositonPacket(playerActorId, 0x1));
|
subpackets.Add(CreateSpawnPositonPacket(0x1));
|
||||||
subpackets.Add(CreateNamePacket(playerActorId));
|
subpackets.Add(CreateNamePacket());
|
||||||
subpackets.Add(CreateStatePacket(playerActorId));
|
subpackets.Add(CreateStatePacket());
|
||||||
subpackets.Add(CreateIsZoneingPacket(playerActorId));
|
subpackets.Add(CreateIsZoneingPacket());
|
||||||
subpackets.Add(CreateScriptBindPacket(playerActorId));
|
subpackets.Add(CreateScriptBindPacket());
|
||||||
return BasePacket.CreatePacket(subpackets, true, false);
|
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.quantity = 1;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
|
|
||||||
Item gItem = Server.GetItemGamedata(itemId);
|
ItemData gItem = Server.GetItemGamedata(itemId);
|
||||||
itemType = gItem.isExclusive ? (byte)0x3 : (byte)0x0;
|
itemType = gItem.isExclusive ? (byte)0x3 : (byte)0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ using System;
|
|||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.dataobjects
|
namespace FFXIVClassic_Map_Server.dataobjects
|
||||||
{
|
{
|
||||||
class Item
|
class ItemData
|
||||||
{
|
{
|
||||||
//Basic
|
//Basic
|
||||||
public readonly uint catalogID;
|
public readonly uint catalogID;
|
||||||
@ -39,7 +39,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
public readonly int repairLevel;
|
public readonly int repairLevel;
|
||||||
public readonly int repairLicense;
|
public readonly int repairLicense;
|
||||||
|
|
||||||
public Item(MySqlDataReader reader)
|
public ItemData(MySqlDataReader reader)
|
||||||
{
|
{
|
||||||
catalogID = reader.GetUInt32("catalogID");
|
catalogID = reader.GetUInt32("catalogID");
|
||||||
name = reader.GetString("name");
|
name = reader.GetString("name");
|
||||||
@ -50,6 +50,8 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
isExclusive = reader.GetBoolean("isExclusive");
|
isExclusive = reader.GetBoolean("isExclusive");
|
||||||
|
|
||||||
durability = reader.GetInt32("durability");
|
durability = reader.GetInt32("durability");
|
||||||
|
sellPrice = reader.GetInt32("sellPrice");
|
||||||
|
|
||||||
icon = reader.GetInt32("icon");
|
icon = reader.GetInt32("icon");
|
||||||
kind = reader.GetInt32("kind");
|
kind = reader.GetInt32("kind");
|
||||||
rarity = reader.GetInt32("rarity");
|
rarity = reader.GetInt32("rarity");
|
||||||
@ -387,7 +389,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class EquipmentItem : Item
|
class EquipmentItem : ItemData
|
||||||
{
|
{
|
||||||
//graphics
|
//graphics
|
||||||
public readonly uint graphicsWeaponId;
|
public readonly uint graphicsWeaponId;
|
||||||
@ -467,6 +469,11 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
|
|
||||||
class WeaponItem : EquipmentItem
|
class WeaponItem : EquipmentItem
|
||||||
{
|
{
|
||||||
|
//extra graphics
|
||||||
|
public readonly uint graphicsOffhandWeaponId;
|
||||||
|
public readonly uint graphicsOffhandEquipmentId;
|
||||||
|
public readonly uint graphicsOffhandVariantId;
|
||||||
|
|
||||||
//weapon sheet
|
//weapon sheet
|
||||||
public readonly short attack;
|
public readonly short attack;
|
||||||
public readonly short magicAttack;
|
public readonly short magicAttack;
|
||||||
@ -497,6 +504,13 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
public WeaponItem(MySqlDataReader reader)
|
public WeaponItem(MySqlDataReader reader)
|
||||||
: base(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");
|
attack = reader.GetInt16("attack");
|
||||||
magicAttack = reader.GetInt16("magicAttack");
|
magicAttack = reader.GetInt16("magicAttack");
|
||||||
craftProcessing = reader.GetInt16("craftProcessing");
|
craftProcessing = reader.GetInt16("craftProcessing");
|
@ -1,6 +1,6 @@
|
|||||||
using FFXIVClassic_Map_Server;
|
using FFXIVClassic_Map_Server;
|
||||||
using FFXIVClassic.Common;
|
using FFXIVClassic.Common;
|
||||||
using FFXIVClassic_Map_Server.packets;
|
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
using FFXIVClassic_Map_Server.packets.send.actor;
|
using FFXIVClassic_Map_Server.packets.send.actor;
|
||||||
@ -12,66 +12,34 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.dataobjects
|
namespace FFXIVClassic_Map_Server.dataobjects
|
||||||
{
|
{
|
||||||
class ConnectedPlayer
|
class Session
|
||||||
{
|
{
|
||||||
public uint actorID = 0;
|
public uint id = 0;
|
||||||
Player playerActor;
|
Player playerActor;
|
||||||
public List<Actor> actorInstanceList = new List<Actor>();
|
public List<Actor> actorInstanceList = new List<Actor>();
|
||||||
|
|
||||||
public uint languageCode = 1;
|
public uint languageCode = 1;
|
||||||
|
|
||||||
private ClientConnection zoneConnection;
|
|
||||||
private ClientConnection chatConnection;
|
|
||||||
|
|
||||||
private uint lastPingPacket = Utils.UnixTimeStampUTC();
|
private uint lastPingPacket = Utils.UnixTimeStampUTC();
|
||||||
|
|
||||||
|
public bool isUpdatesLocked = true;
|
||||||
|
|
||||||
public string errorMessage = "";
|
public string errorMessage = "";
|
||||||
|
|
||||||
public ConnectedPlayer(uint actorId)
|
public Session(uint sessionId)
|
||||||
{
|
{
|
||||||
this.actorID = actorId;
|
this.id = sessionId;
|
||||||
playerActor = new Player(this, actorId);
|
playerActor = new Player(this, sessionId);
|
||||||
actorInstanceList.Add(playerActor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetConnection(int type, ClientConnection conn)
|
public void QueuePacket(List<SubPacket> packets)
|
||||||
{
|
{
|
||||||
conn.connType = type;
|
foreach (SubPacket s in packets)
|
||||||
switch (type)
|
QueuePacket(s);
|
||||||
{
|
|
||||||
case BasePacket.TYPE_ZONE:
|
|
||||||
zoneConnection = conn;
|
|
||||||
break;
|
|
||||||
case BasePacket.TYPE_CHAT:
|
|
||||||
chatConnection = conn;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsClientConnectionsReady()
|
public void QueuePacket(SubPacket subPacket)
|
||||||
{
|
{
|
||||||
return (zoneConnection != null && chatConnection != null);
|
subPacket.SetTargetId(id);
|
||||||
}
|
Server.GetWorldConnection().QueuePacket(subPacket);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player GetActor()
|
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)
|
public void UpdatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState)
|
||||||
{
|
{
|
||||||
|
if (isUpdatesLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
playerActor.oldPositionX = playerActor.positionX;
|
playerActor.oldPositionX = playerActor.positionX;
|
||||||
playerActor.oldPositionY = playerActor.positionY;
|
playerActor.oldPositionY = playerActor.positionY;
|
||||||
playerActor.oldPositionZ = playerActor.positionZ;
|
playerActor.oldPositionZ = playerActor.positionZ;
|
||||||
@ -109,12 +80,15 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
playerActor.rotation = rot;
|
playerActor.rotation = rot;
|
||||||
playerActor.moveState = moveState;
|
playerActor.moveState = moveState;
|
||||||
|
|
||||||
GetActor().zone.UpdateActorPosition(GetActor());
|
GetActor().GetZone().UpdateActorPosition(GetActor());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
long lastMilis = 0;
|
||||||
public void UpdateInstance(List<Actor> list)
|
public void UpdateInstance(List<Actor> list)
|
||||||
{
|
{
|
||||||
|
if (isUpdatesLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
List<BasePacket> basePackets = new List<BasePacket>();
|
List<BasePacket> basePackets = new List<BasePacket>();
|
||||||
List<SubPacket> RemoveActorSubpackets = new List<SubPacket>();
|
List<SubPacket> RemoveActorSubpackets = new List<SubPacket>();
|
||||||
List<SubPacket> posUpdateSubpackets = new List<SubPacket>();
|
List<SubPacket> posUpdateSubpackets = new List<SubPacket>();
|
||||||
@ -124,7 +98,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
{
|
{
|
||||||
if (!list.Contains(actorInstanceList[i]))
|
if (!list.Contains(actorInstanceList[i]))
|
||||||
{
|
{
|
||||||
GetActor().QueuePacket(RemoveActorPacket.BuildPacket(playerActor.actorId, actorInstanceList[i].actorId));
|
QueuePacket(RemoveActorPacket.BuildPacket(actorInstanceList[i].actorId));
|
||||||
actorInstanceList.RemoveAt(i);
|
actorInstanceList.RemoveAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,13 +113,18 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
|
|
||||||
if (actorInstanceList.Contains(actor))
|
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
|
else
|
||||||
{
|
{
|
||||||
GetActor().QueuePacket(actor.GetSpawnPackets(playerActor.actorId, 1));
|
QueuePacket(actor.GetSpawnPackets(playerActor, 1));
|
||||||
GetActor().QueuePacket(actor.GetInitPackets(playerActor.actorId));
|
|
||||||
GetActor().QueuePacket(actor.GetSetEventStatusPackets(playerActor.actorId));
|
QueuePacket(actor.GetInitPackets());
|
||||||
|
QueuePacket(actor.GetSetEventStatusPackets());
|
||||||
actorInstanceList.Add(actor);
|
actorInstanceList.Add(actor);
|
||||||
|
|
||||||
if (actor is Npc)
|
if (actor is Npc)
|
||||||
@ -163,5 +142,10 @@ namespace FFXIVClassic_Map_Server.dataobjects
|
|||||||
actorInstanceList.Clear();
|
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.director;
|
||||||
using FFXIVClassic_Map_Server.Actors;
|
using FFXIVClassic_Map_Server.Actors;
|
||||||
using FFXIVClassic_Map_Server.dataobjects;
|
using FFXIVClassic_Map_Server.dataobjects;
|
||||||
@ -13,200 +13,425 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using FFXIVClassic_Map_Server.lua;
|
using FFXIVClassic_Map_Server.lua;
|
||||||
|
using FFXIVClassic.Common;
|
||||||
|
using FFXIVClassic_Map_Server.actors.area;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.lua
|
namespace FFXIVClassic_Map_Server.lua
|
||||||
{
|
{
|
||||||
class LuaEngine
|
class LuaEngine
|
||||||
{
|
{
|
||||||
const string FILEPATH_PLAYER = "./scripts/player.lua";
|
public const string FILEPATH_PLAYER = "./scripts/player.lua";
|
||||||
const string FILEPATH_ZONE = "./scripts/zones/{0}/zone.lua";
|
public const string FILEPATH_ZONE = "./scripts/unique/{0}/zone.lua";
|
||||||
const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua";
|
public const string FILEPATH_CONTENT = "./scripts/content/{0}.lua";
|
||||||
const string FILEPATH_DIRECTORS = "./scripts/directors/{0}.lua";
|
public const string FILEPATH_COMMANDS = "./scripts/commands/{0}.lua";
|
||||||
const string FILEPATH_NPCS = "./scripts/zones/{0}/npcs/{1}.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;
|
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)
|
return mThisEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
if (entry.Value <= currentTime)
|
||||||
if (File.Exists(luaPath))
|
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
|
||||||
{
|
{
|
||||||
LuaScript script = LoadScript(luaPath);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
if (script == null)
|
private static string GetScriptPath(Actor target)
|
||||||
return null;
|
{
|
||||||
|
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 "";
|
||||||
|
}
|
||||||
|
|
||||||
DynValue result = script.Call(script.Globals["init"], target);
|
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;
|
||||||
|
|
||||||
|
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);
|
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||||
return lparams;
|
return lparams;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
if (!optional)
|
||||||
return null;
|
SendError(player, String.Format("Could not find function '{0}' for actor {1}.", funcName, target.GetName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!optional)
|
||||||
|
SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Coroutine DoActorOnEventStarted(Player player, Actor target, EventStartPacket eventStart)
|
public List<LuaParam> CallLuaFunctionForReturn(string path, string funcName, bool optional, params object[] args)
|
||||||
{
|
{
|
||||||
string luaPath;
|
string luaPath = path;
|
||||||
|
LuaScript script = LoadScript(luaPath);
|
||||||
if (target is Command)
|
if (script != null)
|
||||||
{
|
{
|
||||||
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName());
|
if (!script.Globals.Get(funcName).IsNil())
|
||||||
|
{
|
||||||
|
//Run Script
|
||||||
|
DynValue result = script.Call(script.Globals[funcName], args);
|
||||||
|
List<LuaParam> lparams = LuaUtils.CreateLuaParamList(result);
|
||||||
|
return lparams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (target is Director)
|
return null;
|
||||||
{
|
|
||||||
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
|
||||||
|
|
||||||
if (File.Exists(luaPath))
|
|
||||||
{
|
|
||||||
LuaScript script = LoadScript(luaPath);
|
|
||||||
|
|
||||||
if (script == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (!script.Globals.Get("onEventStarted").IsNil())
|
|
||||||
return script.CreateCoroutine(script.Globals["onEventStarted"]).Coroutine;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DoActorOnSpawn(Player player, Npc target)
|
public void CallLuaFunction(Player player, Actor target, string funcName, bool optional, params object[] args)
|
||||||
{
|
|
||||||
string luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
|
||||||
|
|
||||||
if (File.Exists(luaPath))
|
|
||||||
{
|
|
||||||
LuaScript script = LoadScript(luaPath);
|
|
||||||
|
|
||||||
if (script == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//Run Script
|
|
||||||
if (!script.Globals.Get("onSpawn").IsNil())
|
|
||||||
script.Call(script.Globals["onSpawn"], player, target);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DoActorOnEventUpdated(Player player, Actor target, EventUpdatePacket eventUpdate)
|
|
||||||
{
|
{
|
||||||
|
//Need a seperate case for NPCs cause that child/parent thing.
|
||||||
if (target is Npc)
|
if (target is Npc)
|
||||||
{
|
{
|
||||||
((Npc)target).DoEventUpdate(player, eventUpdate);
|
CallLuaFunctionNpc(player, (Npc)target, funcName, optional, args);
|
||||||
return;
|
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)
|
string luaPath = GetScriptPath(target);
|
||||||
luaPath = String.Format(FILEPATH_COMMANDS, target.GetName());
|
LuaScript script = LoadScript(luaPath);
|
||||||
else if (target is Director)
|
if (script != null)
|
||||||
luaPath = String.Format(FILEPATH_DIRECTORS, target.GetName());
|
|
||||||
else
|
|
||||||
luaPath = String.Format(FILEPATH_NPCS, target.zoneId, target.GetName());
|
|
||||||
|
|
||||||
if (File.Exists(luaPath))
|
|
||||||
{
|
{
|
||||||
LuaScript script = LoadScript(luaPath);
|
if (!script.Globals.Get(funcName).IsNil())
|
||||||
|
{
|
||||||
if (script == null)
|
Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
|
||||||
return;
|
DynValue value = coroutine.Resume(args2);
|
||||||
|
ResolveResume(player, coroutine, value);
|
||||||
//Have to Do this to combine LuaParams
|
}
|
||||||
List<Object> objects = new List<Object>();
|
else
|
||||||
objects.Add(player);
|
{
|
||||||
objects.Add(target);
|
if (!optional)
|
||||||
objects.Add(eventUpdate.val2);
|
SendError(player, String.Format("Could not find function '{0}' for actor {1}.", funcName, target.GetName()));
|
||||||
objects.AddRange(LuaUtils.CreateLuaParamObjectList(eventUpdate.luaParams));
|
}
|
||||||
|
|
||||||
//Run Script
|
|
||||||
if (!script.Globals.Get("onEventUpdate").IsNil())
|
|
||||||
script.Call(script.Globals["onEventUpdate"], objects.ToArray());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendError(player, String.Format("ERROR: Could not find script for actor {0}.", target.GetName()));
|
if (!(target is Area) && !optional)
|
||||||
|
SendError(player, String.Format("Could not find script for actor {0}.", target.GetName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void OnZoneIn(Player player)
|
public void EventStarted(Player player, Actor target, EventStartPacket eventStart)
|
||||||
{
|
{
|
||||||
string luaPath = String.Format(FILEPATH_ZONE, player.GetZone().actorId);
|
List<LuaParam> lparams = eventStart.luaParams;
|
||||||
|
lparams.Insert(0, new LuaParam(2, eventStart.triggerName));
|
||||||
if (File.Exists(luaPath))
|
if (mSleepingOnPlayerEvent.ContainsKey(player.actorId))
|
||||||
{
|
{
|
||||||
LuaScript script = LoadScript(luaPath);
|
Coroutine coroutine = mSleepingOnPlayerEvent[player.actorId];
|
||||||
|
mSleepingOnPlayerEvent.Remove(player.actorId);
|
||||||
|
|
||||||
if (script == null)
|
try{
|
||||||
return;
|
DynValue value = coroutine.Resume();
|
||||||
|
ResolveResume(null, coroutine, value);
|
||||||
//Run Script
|
}
|
||||||
if (!script.Globals.Get("onZoneIn").IsNil())
|
catch (ScriptRuntimeException e)
|
||||||
script.Call(script.Globals["onZoneIn"], player);
|
{
|
||||||
|
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 OnBeginLogin(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);
|
GetInstance().AddWaitEventCoroutine(player, coroutine);
|
||||||
|
|
||||||
if (script == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//Run Script
|
|
||||||
if (!script.Globals.Get("onBeginLogin").IsNil())
|
|
||||||
script.Call(script.Globals["onBeginLogin"], player);
|
|
||||||
}
|
}
|
||||||
}
|
else if (value.Tuple != null && value.Tuple.Length >= 1 && value.Tuple[0].String != null)
|
||||||
|
|
||||||
public static void OnLogin(Player player)
|
|
||||||
{
|
|
||||||
if (File.Exists(FILEPATH_PLAYER))
|
|
||||||
{
|
{
|
||||||
LuaScript script = LoadScript(FILEPATH_PLAYER);
|
switch (value.Tuple[0].String)
|
||||||
|
{
|
||||||
if (script == null)
|
case "_WAIT_TIME":
|
||||||
return;
|
GetInstance().AddWaitCoroutine(coroutine, (float)value.Tuple[1].Number);
|
||||||
|
break;
|
||||||
//Run Script
|
case "_WAIT_SIGNAL":
|
||||||
if (!script.Globals.Get("onLogin").IsNil())
|
GetInstance().AddWaitSignalCoroutine(coroutine, (string)value.Tuple[1].String);
|
||||||
script.Call(script.Globals["onLogin"], player);
|
break;
|
||||||
|
case "_WAIT_EVENT":
|
||||||
|
GetInstance().AddWaitEventCoroutine((Player)value.Tuple[1].UserData.Object, coroutine);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region RunGMCommand
|
#region RunGMCommand
|
||||||
public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false)
|
public static void RunGMCommand(Player player, String cmd, string[] param, bool help = false)
|
||||||
{
|
{
|
||||||
|
bool playerNull = player == null;
|
||||||
|
if (playerNull && param.Length >= 3)
|
||||||
|
player = Server.GetWorldManager().GetPCInWorld(param[1] + " " + param[2]);
|
||||||
|
|
||||||
// load from scripts/commands/gm/ directory
|
// 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
|
// check if the file exists
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
@ -290,7 +515,7 @@ namespace FFXIVClassic_Map_Server.lua
|
|||||||
// we'll push our lua params here
|
// we'll push our lua params here
|
||||||
List<object> LuaParam = new List<object>();
|
List<object> LuaParam = new List<object>();
|
||||||
|
|
||||||
var i = 0;
|
var i = playerNull ? 2 : 0;
|
||||||
for (; i < parameters.Length; ++i)
|
for (; i < parameters.Length; ++i)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -326,10 +551,14 @@ namespace FFXIVClassic_Map_Server.lua
|
|||||||
// the script can double check the player exists, we'll push them anyways
|
// the script can double check the player exists, we'll push them anyways
|
||||||
LuaParam.Insert(0, player);
|
LuaParam.Insert(0, player);
|
||||||
// push the arg count too
|
// push the arg count too
|
||||||
LuaParam.Insert(1, i);
|
LuaParam.Insert(1, i - (playerNull ? 2 : 0));
|
||||||
|
|
||||||
// run the script
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,17 +567,20 @@ namespace FFXIVClassic_Map_Server.lua
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static LuaScript LoadScript(string filename)
|
public static LuaScript LoadScript(string path)
|
||||||
{
|
{
|
||||||
|
if (!File.Exists(path))
|
||||||
|
return null;
|
||||||
|
|
||||||
LuaScript script = LoadGlobals();
|
LuaScript script = LoadGlobals();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
script.DoFile(filename);
|
script.DoFile(path);
|
||||||
}
|
}
|
||||||
catch (SyntaxErrorException e)
|
catch (SyntaxErrorException e)
|
||||||
{
|
{
|
||||||
Program.Log.Error("LUAERROR: {0}.", e.DecoratedMessage);
|
Program.Log.Error("{0}.", e.DecoratedMessage);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return script;
|
return script;
|
||||||
@ -362,8 +594,11 @@ namespace FFXIVClassic_Map_Server.lua
|
|||||||
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
|
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
|
||||||
script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
|
script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
|
||||||
script.Globals["GetStaticActor"] = (Func<string, Actor>)Server.GetStaticActors;
|
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["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); };
|
script.Options.DebugPrint = s => { Program.Log.Debug(s); };
|
||||||
return script;
|
return script;
|
||||||
@ -371,53 +606,14 @@ namespace FFXIVClassic_Map_Server.lua
|
|||||||
|
|
||||||
public static void SendError(Player player, string message)
|
public static void SendError(Player player, string message)
|
||||||
{
|
{
|
||||||
|
message = "[LuaError] " + message;
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
List<SubPacket> SendError = new List<SubPacket>();
|
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.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>();
|
List<LuaParam> luaParams = new List<LuaParam>();
|
||||||
|
|
||||||
|
if (fromScript == null)
|
||||||
|
return luaParams;
|
||||||
|
|
||||||
if (fromScript.Type == DataType.Tuple)
|
if (fromScript.Type == DataType.Tuple)
|
||||||
{
|
{
|
||||||
foreach (DynValue d in fromScript.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
|
namespace FFXIVClassic_Map_Server.packets.receive
|
||||||
{
|
{
|
||||||
class _0x07Packet
|
class ZoneInCompletePacket
|
||||||
{
|
{
|
||||||
public bool invalidPacket = false;
|
public bool invalidPacket = false;
|
||||||
public uint timestamp;
|
public uint timestamp;
|
||||||
public uint unknown;
|
public int unknown;
|
||||||
|
|
||||||
public _0x07Packet(byte[] data)
|
public ZoneInCompletePacket(byte[] data)
|
||||||
{
|
{
|
||||||
using (MemoryStream mem = new MemoryStream(data))
|
using (MemoryStream mem = new MemoryStream(data))
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ namespace FFXIVClassic_Map_Server.packets.receive
|
|||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
timestamp = binReader.ReadUInt32();
|
timestamp = binReader.ReadUInt32();
|
||||||
unknown = binReader.ReadUInt32();
|
unknown = binReader.ReadInt32();
|
||||||
}
|
}
|
||||||
catch (Exception){
|
catch (Exception){
|
||||||
invalidPacket = true;
|
invalidPacket = true;
|
@ -63,7 +63,10 @@ namespace FFXIVClassic_Map_Server.packets.receive.events
|
|||||||
|
|
||||||
binReader.BaseStream.Seek(0x31, SeekOrigin.Begin);
|
binReader.BaseStream.Seek(0x31, SeekOrigin.Begin);
|
||||||
|
|
||||||
luaParams = LuaUtils.ReadLuaParams(binReader);
|
if (binReader.PeekChar() == 0x1)
|
||||||
|
luaParams = new List<LuaParam>();
|
||||||
|
else
|
||||||
|
luaParams = LuaUtils.ReadLuaParams(binReader);
|
||||||
}
|
}
|
||||||
catch (Exception){
|
catch (Exception){
|
||||||
invalidPacket = true;
|
invalidPacket = true;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user