Jump to content
  • 0

How packets works? How read it or write one new?


Zell

Question


  • Group:  Members
  • Topic Count:  53
  • Topics Per Day:  0.01
  • Content Count:  411
  • Reputation:   260
  • Joined:  04/25/12
  • Last Seen:  

Hi, I'm studying some stuffs and have a question, how does packet works? I mean, I know what they are, but how to read or write a new one? I THINK I know to read this, but whow to write a new one?

 

For sample, we have the "mes" commands.

 

BUILDIN_FUNC(mes)
{
TBL_PC* sd = script_rid2sd(st);
if( sd == NULL )
return 0;
 
if( !script_hasdata(st, 3) )
{// only a single line detected in the script
clif_scriptmes(sd, st->oid, script_getstr(st, 2));
}
else
{// parse multiple lines as they exist
int i;
 
for( i = 2; script_hasdata(st, i); i++ )
{
// send the message to the client
clif_scriptmes(sd, st->oid, script_getstr(st, i));
}
}
 
st->mes_active = 1; // Invoking character has a NPC dialog box open.
return SCRIPT_CMD_SUCCESS;
}

 

Packet:

/// Displays an NPC dialog message (ZC_SAY_DIALOG).
/// 00b4 <packet len>.W <npc id>.L <message>.?B
/// Client behavior (dialog window):
/// - disable mouse targeting
/// - open the dialog window
/// - set npcid of dialog window (0 by default)
/// - if set to clear on next mes, clear contents
/// - append this text
void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes)
{
int fd = sd->fd;
int slen = strlen(mes) + 9;
 
WFIFOHEAD(fd, slen);
WFIFOW(fd,0)=0xb4;
WFIFOW(fd,2)=slen;
WFIFOL(fd,4)=npcid;
memcpy((char*)WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));
}

 
Whow to understand this?
 
/// 00b4 <packet len>.W <npc id>.L <message>.?B
 
In packet_db.txt we have:
 
0x00b4,-1
 
This mean that the packet len change your size.
 
But some packets like the next button, are like this:
 
0x00b5,6
 
Why the packet lenght of next button are "6"? The next button return some value or send? I'm confuse.
 

// 01. PacketType       ID of the packet.
// 02. PacketLength     Length of the packet. If 0, packet is disabled in current packet version. If -1, packet has variable size.
// 03. Name             Name of the packet parser function (optional, for incoming packets only).
// 04. FieldIndex       Specifies the offset of a packet field in bytes from the begin of the packet (only specified when Name is given).
//                      Can be 0, when the layout is not known.
 
What is the FieldIndex?
 
And for sample, if I want to write a new packet? I search for a ID not used? Just this? If i want to send for sample a "name" in a new packet? I don't need the C code, just the packet explain and maybe the clif code, but I think that I understood this.
 
Any way, thanks for who help or read this.
 
Sorry about english.
Edited by Zell
Link to comment
Share on other sites

5 answers to this question

Recommended Posts


  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  657
  • Reputation:   662
  • Joined:  11/12/12
  • Last Seen:  

Heya!

WFIFOHEAD(fd, slen);
WFIFOW(fd,0)=0xb4;
WFIFOW(fd,2)=slen;
WFIFOL(fd,4)=npcid;
memcpy((char*)WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));

Let's say you want to send the message "hello", slen being 5 + 9 = 14.

 

First call is obvious, sets the length of the packet.

WFIFOW means "Write a Word to the socket (a Word is 2 bytes - uint16) at position 0", giving you the following raw output so far :

0xb4 0x00 - ...

It is reversed because of the endianness, which is "always" in little-endian.

 

WFIFOW(fd,2), same as above, giving you (14 = 0x0E) : 

0xb4 0x00 - 0x0E 0x00 - ...

 

WFIFOL means "Write a Long to the socket (a Long is 4 bytes - uint32) at position 4", giving you the following raw output so far (let's say the npcid is 297520349 = 0x11BBCCDD) :

0xb4 0x00 - 0x0E 0x00 - 0xDD 0xCC 0xBB 0x11 - ...

 

WFIFOP retrieves the char pointer for the writing socket buffer at the specified position. memcpy simply copies the content of mes ("hello") to that position. Giving you...

0xb4 0x00 - 0x0E 0x00 - 0xDD 0xCC 0xBB 0x11 - 0x48 0x65 0x6c 0x6c 0x6f 0x00

WFIFOSET sets the buffer to the correct position to send it (WFIFOW actually returns a pointer to the position, so in this case it's handy because it returns slen; then again it's a bit pointless, it could have just been "WFIFOSET(fd,slen);" and it would be clearer).

 

/// 00b4 <packet len>.W <npc id>.L <message>.?B

This means 0x00b4 is your packet id, followed by a Word (packet length), followed by a Long (npc id), followed by a variable number of bytes (your message).

 

0x00b4,-1

That means the size of the packet is unknown/variable (indeed, the message can be of any size).

 

0x00b5,6

That means the size of the packet is always 6 bytes. In this case, the first 2 bytes are the packet ID, the next 4 bytes are the npc id, or : 00b5 <npc id>.L

 

The packet field can be used for something like... 0x00b5,6,clif_scriptnext,2; - this can help you retrieve the positions more easily. For example :
packet_db[sd->packet_ver][RFIFOW(fd,0) /* packet id */].pos[0] // pos[0] here is the "2" you defined earlier. Some packet_ver defines different indexes for the same packet, that's why it's useful not to use pre-defined values.
 

To write a new packet, you have the right idea. Find a packet not used, go in a high range to avoid further conflicts. Also there's a packet limit, not really sure where it's defined on rAthena though.

Edited by Tokei
  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  53
  • Topics Per Day:  0.01
  • Content Count:  411
  • Reputation:   260
  • Joined:  04/25/12
  • Last Seen:  

Heey, thanks toekei, you are always support me :D

 

So, you cleared my mind in some aspects. Just a little more questions and I will discovery the rest by me, thank!

 

Why this?

 

[/code]

int slen = strlen(mes) + 9;

[/code]

 

Why the "+ 9"?

 

Let me see if I understood:

 

WFIFOW(fd,0)=0xb4;

 

In this line i set the two "values" (just for reference) of packet?

 

0x48 0x65 0x6c 0x6c 0x6f 0x00

 H       e       l        l        o      ?(What the purpose of this 0x00?)

 

Its just a space?

 

Here too

 

WFIFOW(fd,2), same as above, giving you (14 = 0x0E) : 

0xb4 0x00 - 0x0E 0x00 - ...

 

And amazing, while writing this post I realize the other things, now I undersant how to make this, now I can read hahaha, thank you so much! I have just this questions more

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  657
  • Reputation:   662
  • Joined:  11/12/12
  • Last Seen:  

In C and C++, strings are null-terminated, meaning they must end with '\0' (which is 0x00 in hex). If you omit this 0x00, the end of the string cannot be seen and it will read whatever's currently in your memory until it finds a 0x00.

 

The + 9 is for the total length of the packet. packet length = 2 bytes (packet id) + 2 bytes (string length) + 4 bytes (npc id) + strlen(mes) bytes (number of characters in your message) + 1 byte (null-terminated char byte) = strlen(mes) + 9

 

If you take a look at the memcpy line, it copies 6 characters but the string "hello" is actually only 5 characters (slen - 8 = 14 - 8 = 6). This when it copies that 0x00.

 

For any strings in C, writing this is wrong : 

char c[5] = "hello";

It needs to be :

char c[6] = "hello";

 

 

WFIFOW(fd,0)=0xb4;

In this line i set the two "values" (just for reference) of packet?

 

Not really sure what you mean here! 0xb4 is a "shortcut" for 0x000000b4. The compiler converts it to a Word for you, so : 0x00b4, which is swapped around to 0xb4 0x00. So I guess that yes, you set the two values with this line. That explanation may not be 100% accurate, but it's close enough. If you had... 0xfb4, you'd get 0xb4 0x0f. If you had 0xaabb0f, you'd get 0x0f 0xbb (that 0xaa is 'lost' because it goes beyond the uint16 range of 2 bytes).

Edited by Tokei
  • Upvote 3
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  53
  • Topics Per Day:  0.01
  • Content Count:  411
  • Reputation:   260
  • Joined:  04/25/12
  • Last Seen:  

Thanks, with this informations I will take a study!

Edited by Zell
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  1
  • Reputation:   0
  • Joined:  01/23/14
  • Last Seen:  

Hey guys, I was trying to understand how packets work and find this topic that helped me a lot. But I still don't understand how I can associate an image like the close button and the next button or some message in msgstringtable with the packets sent to the client. How do the client knows how to find a specific image or some content in data folder and put it on screen?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...