Skip to content

Commit

Permalink
feat: Update RPC packet handling
Browse files Browse the repository at this point in the history
- Added a new handler for RPC packet contents.
- Identified a few new RPC packets and added their definitions which can
  be used by the new handler.
  • Loading branch information
pacampbell committed May 1, 2024
1 parent 8f47710 commit f43c863
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 33 deletions.
37 changes: 4 additions & 33 deletions Arrowgene.Ddon.GameServer/Handler/LobbyLobbyDataMsgHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Entity.RpcPacketStructure;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Logging;

namespace Arrowgene.Ddon.GameServer.Handler
Expand Down Expand Up @@ -53,39 +55,8 @@ public override void Handle(GameClient client, StructurePacket<C2SLobbyLobbyData
}
}

if(packet.Structure.RpcPacket.Length > 52)
{
IBuffer rpcPacketBuffer = new StreamBuffer(packet.Structure.RpcPacket);
rpcPacketBuffer.SetPositionStart();

// nNetMsgData::Head::deserialize
uint sessionId = rpcPacketBuffer.ReadUInt32(Endianness.Big); // NetMsgData.Head.SessionId
ulong rpcId = rpcPacketBuffer.ReadUInt64(Endianness.Big); // NetMsgData.Head.RpcId
uint msgIdFull = rpcPacketBuffer.ReadUInt32(Endianness.Big); // NetMsgData.Head.MsgIdFull
uint searchId = rpcPacketBuffer.ReadUInt32(Endianness.Big); // NetMsgData.Head.SearchId, seems to either a PawnId or 0

// There is theoretically a nNetMsgData::Base, but i cant even see the code that deserializes it in the client

// nNetMsgData::CtrlBase::deserialize
rpcPacketBuffer.ReadUInt64(Endianness.Big); // nNetMsgData::CtrlBase::stMsgCtrlBaseData.mUniqueId ?

// Apparently all received 3.4.16s:
// - Have searchID of 0 (aren't related to pawns)
// - Have CtrlBaseData.mUniqueId of 0x8000000000000001

// nNetMsgData::CtrlAction::deserialize
bool isEnemy = rpcPacketBuffer.ReadBool(); // NetMsgData.CtrlAction.IsEnemy
bool isCharacter = rpcPacketBuffer.ReadBool(); // NetMsgData.CtrlAction.IsCharacter
bool isHuman = rpcPacketBuffer.ReadBool(); // NetMsgData.CtrlAction.IsHuman
bool isEnemyLarge = rpcPacketBuffer.ReadBool(); // NetMsgData.CtrlAction.IsEnemyLarge

// From now on, the contents (subpackets) depend on MsgId, a set of flags
if((msgIdFull & 1) != 0) { // This is incomplete, msgIdFull is converted through a function first, (0x5FE8D0) but should work for most cases
client.Character.X = rpcPacketBuffer.ReadDouble(Endianness.Big);
client.Character.Y = rpcPacketBuffer.ReadFloat(Endianness.Big);
client.Character.Z = rpcPacketBuffer.ReadDouble(Endianness.Big);
}
}
// Handle additional packet contents
RpcHandler.Handle(client, packet.Structure.Type, packet.Structure.RpcPacket);
}
}
}
36 changes: 36 additions & 0 deletions Arrowgene.Ddon.GameServer/Handler/RpcHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Entity.RpcPacketStructure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Arrowgene.Ddon.GameServer.Handler
{
public class RpcHandler
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(RpcHandler));

public static void Handle(GameClient client, byte packetType, byte[] rpcData)
{
IBuffer buffer = new StreamBuffer(rpcData);
buffer.SetPositionStart();

RpcPacketHeader Header = new RpcPacketHeader().Read(buffer);
if (gRpcPacketHandlers.ContainsKey(Header.MsgIdFull))
{
gRpcPacketHandlers[Header.MsgIdFull].Handle(client.Character, buffer);
}
}

public static readonly Dictionary<RpcMessageId, IRpcPacket> gRpcPacketHandlers = new Dictionary<RpcMessageId, IRpcPacket>()
{
{RpcMessageId.HeartBeat1, new RpcHeartbeatPacket()},
};
}
}
11 changes: 11 additions & 0 deletions Arrowgene.Ddon.Shared/Entity/RpcPacketStructure/IRpcPacket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Shared.Model;
using System;

namespace Arrowgene.Ddon.Shared.Entity.RpcPacketStructure
{
public interface IRpcPacket
{
public void Handle(Character character, IBuffer buffer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Shared.Model;
using System;

namespace Arrowgene.Ddon.Shared.Entity.RpcPacketStructure
{
public class RpcHeartbeatPacket : RpcPacketBase
{
public RpcHeartbeatPacket()
{
}

public UInt64 Unk0 { get; set; }
public bool IsEnemy { get; set; }
public bool IsCharacter { get; set; }
public bool IsHuman { get; set; }
public bool IsEnemyLarge { get; set; }

public double PosX { get; set; }
public float PosY { get; set; }
public double PosZ { get; set; }

public UInt32 Unk1 { get; set; }
public UInt32 Unk2 { get; set; }
public UInt32 Unk3 { get; set; }

public UInt16 GreenHP { get; set; }
public UInt16 WhiteHP { get; set; }
public UInt16 Unk4 { get; set; }
public UInt16 Stamina { get; set; }

public override void Handle(Character character, IBuffer buffer)
{
RpcHeartbeatPacket obj = Read(buffer);

if (obj.IsCharacter)
{
character.X = obj.PosX;
character.Y = obj.PosY;
character.Z = obj.PosZ;
}
}

private RpcHeartbeatPacket Read(IBuffer buffer)
{
RpcHeartbeatPacket obj = new RpcHeartbeatPacket();
obj.Unk0 = ReadUInt64(buffer); // nNetMsgData::CtrlBase::stMsgCtrlBaseData.mUniqueId ?
obj.IsEnemy = ReadBool(buffer);
obj.IsCharacter = ReadBool(buffer);
obj.IsHuman = ReadBool(buffer);
obj.IsEnemyLarge = ReadBool(buffer);
obj.PosX = ReadDouble(buffer);
obj.PosY = ReadFloat(buffer);
obj.PosZ = ReadDouble(buffer);
obj.Unk1 = ReadUInt32(buffer);
obj.Unk2 = ReadUInt32(buffer);
obj.Unk3 = ReadUInt32(buffer);
obj.GreenHP = ReadUInt16(buffer);
obj.WhiteHP = ReadUInt16(buffer);
obj.Unk4 = ReadUInt16(buffer);
obj.Stamina = ReadUInt16(buffer);
return obj;
}
}
}
33 changes: 33 additions & 0 deletions Arrowgene.Ddon.Shared/Entity/RpcPacketStructure/RpcLoginPacket.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Shared.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Arrowgene.Ddon.Shared.Entity.RpcPacketStructure
{
public class RpcLoginPacket : RpcPacketBase
{
public RpcLoginPacket()
{
Unk0 = new byte[6];
}

public byte[] Unk0 { get; set; }
public UInt16 StageNo { get; set; }

public override void Handle(Character character, IBuffer buffer)
{
RpcLoginPacket obj = Read(buffer);
}
private RpcLoginPacket Read(IBuffer buffer)
{
RpcLoginPacket obj = new RpcLoginPacket();
obj.Unk0 = ReadBytes(buffer, Unk0.Length);
obj.StageNo = ReadUInt16(buffer);
return obj;
}
}
}
54 changes: 54 additions & 0 deletions Arrowgene.Ddon.Shared/Entity/RpcPacketStructure/RpcPacketBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Shared.Model;
using System;

namespace Arrowgene.Ddon.Shared.Entity.RpcPacketStructure
{
public abstract class RpcPacketBase : IRpcPacket
{
public RpcPacketBase()
{
}

public abstract void Handle(Character character, IBuffer buffer);

public byte[] ReadBytes(IBuffer buffer, int length)
{
return buffer.ReadBytes(length);
}

public byte ReadByte(IBuffer buffer)
{
return buffer.ReadByte();
}

public UInt16 ReadUInt16(IBuffer buffer)
{
return buffer.ReadUInt16(Endianness.Big);
}

public UInt32 ReadUInt32(IBuffer buffer)
{
return buffer.ReadUInt32(Endianness.Big);
}

public UInt64 ReadUInt64(IBuffer buffer)
{
return buffer.ReadUInt64(Endianness.Big);
}

public bool ReadBool(IBuffer buffer)
{
return buffer.ReadBool();
}

public double ReadDouble(IBuffer buffer)
{
return buffer.ReadDouble(Endianness.Big);
}
public float ReadFloat(IBuffer buffer)
{
return buffer.ReadFloat(Endianness.Big);
}
}
}
38 changes: 38 additions & 0 deletions Arrowgene.Ddon.Shared/Entity/RpcPacketStructure/RpcPacketHeader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Arrowgene.Ddon.Shared.Entity.RpcPacketStructure
{
public class RpcPacketHeader : RpcPacketBase
{
public RpcPacketHeader()
{
}

public UInt32 SessionId { get; set; }
public UInt64 RpcId { get; set; }
public RpcMessageId MsgIdFull { get; set; }
public UInt32 SearchId { get; set; }

public override void Handle(Character character, IBuffer buffer)
{
/* special case nothing to do */
}

public RpcPacketHeader Read(IBuffer buffer)
{
RpcPacketHeader obj = new RpcPacketHeader();
obj.SessionId = ReadUInt32(buffer); // NetMsgData.Head.SessionId
obj.RpcId = ReadUInt64(buffer); // NetMsgData.Head.RpcId
obj.MsgIdFull = (RpcMessageId) ReadUInt32(buffer); // NetMsgData.Head.MsgIdFull
obj.SearchId = ReadUInt32(buffer); // NetMsgData.Head.SearchId, seems to either a PawnId or 0
return obj;
}
}
}
13 changes: 13 additions & 0 deletions Arrowgene.Ddon.Shared/Model/RpcMessageId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace Arrowgene.Ddon.Shared.Model
{
public enum RpcMessageId : UInt32
{
Login = 0x41000001,
HeartBeat0 = 0x40010002,
HeartBeat1 = 0x40010015,
HeartBeat2 = 0x4001001A,
Combat1 = 0x40010037,
}
}
8 changes: 8 additions & 0 deletions Arrowgene.Ddon.Shared/Model/RpcPacketType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Arrowgene.Ddon.Shared.Model
{
public enum RpcPacketType : byte
{
Ping = 2, // See this while in town and out in the field
Combat = 4, // See this when fighting monsters
}
}

0 comments on commit f43c863

Please sign in to comment.