Oh so sorry about the delayed reply.
You don't need to set each element of the struct, just cast the array of bytes to it, so for example, at my PacketHandler cpp file I have:
Code:
#pragma pack(push)
#pragma pack(1)
typedef struct
{
ushort Length;
ushort OP;
/// We will not take care of the security bytes
} CL_PacketHeaderStruct;
#pragma pack(pop)
CL_PacketHeaderStruct *cl_packetheader;
ubyte *cl_packetcontent;
And maybe you're asking yourself why? that's because you could receive more than 1 packet per communication between Client and Server. So in this case I just need to know where that packet ends and its OP code to call the corresponding Handler:
Code:
void PacketsHandler(CGameObject *go, uint totalBytes)
{
ubyte *buffer = go->GetRecvBuffer();
uint size;
while (totalBytes > 0)
{
cl_packetheader = (CL_PacketHeaderStruct*)&buffer[0];
size = 6 + cl_packetheader->Length;
cl_packetcontent = buffer + 6;
switch (cl_packetheader->OP)
{
case CL_PING:
case CL_HANDSHAKE:
{
break;
}
case CL_WHOAMI:
{
Packet_WhoAmI(go, cl_packetcontent);
break;
}
case CL_PATCH_INFO_REQUEST:
{
Packet_PatchInfo(go, cl_packetcontent);
break;
}
case CL_SERVERLIST_REQUEST:
{
Packet_ServerList(go, cl_packetcontent);
break;
}
case CL_LOGIN_REQUEST:
{
Packet_Login(go, cl_packetcontent);
break;
}
case CL_CHARACTER_OPERATIONS:
{
Packet_Character(go, cl_packetcontent);
break;
}
default:
{
std::cout << "Unknown packet: " << std::hex << cl_packetheader->OP << "\n";
break;
}
}
buffer += size;
totalBytes -= size;
}
}
See how I do cast the bytes here?
Quote:
|
cl_packetheader = (CL_PacketHeaderStruct*)&buffer[0]; <-- this does the work
|
So for fixed size packets you don't have any problems and most of the packets you're sending from your server are several times the same.
Remember what the #pragma pack directive says:
Quote:
|
Members of structures are aligned on the specified byte-alignment, or on their natural alignment boundary, whichever is less.
|
(

)
If it wasn't because of this you couldn't use this method of 'parsing'. That's why it would make an emulator made in C++ faster than one in C# or any similar language.
But yes, here we've to face the fact that not all the packets from the client has the same size... well, I was thinking about a solution to that problem but for now I was using this (for the login packet):
Code:
ushort *namelen = (ushort*)&content[0]; content+=sizeof(ushort);
char *name = (char*)&content[0]; content+=*namelen;
Which is... not the best option in my opinion but maybe you could divide your packet into several structures and then plus the pointer to the previous structure size...
I couldn't find any free time to continue working on that because I was parsing all the skilldata files (that's how I got the complete list of flags of skills modifiers that you have seen further in that thread).
And that leads into another stuff I was thinking about... why do you have to fill up a database with those static values? I mean, you're not developing the new Silkroad Online... it's just an emu. (Edit2: deserialization/serialization is a waste of precious time).
Well, those are just thoughts about the development of an emu in C++.
I'll try to put more things in that thread when I try/test more things.
Edit: I didn't post source before as it's a WIP (work in progress) project.