[Tutorial] Packets - Pawn.RakNet
#1

• Packets - Pawn.RakNet
Other Pawn.RakNet tutorials: RPC - Pawn.RakNet

Systems that run RakNet, communicate through what is known as packets. Or more accurately in the case of UDP, datagrams. Each datagram is created by RakNet and contains one or more messages. Those messages/data could be position, armor, actual vehicle and so on.

The first byte of the packet (8 bits) is it's numeric identifier.

There are different packet identifiers, the most common being:
  • ID_VEHICLE_SYNC (200) = Responsible for vehicle synchronization data. Example: when the player is inside a car. Their position, car health, speed, etc, is the packet data.
  • ID_AIM_SYNC (203) = Responsible for camera synchronization data. Example: Camera vectors, camera zoom, weapon status, object/car/player/actor the player is targeting, etc, is the packet data.
  • ID_BULLET_SYNC (206) = Responsible for bullet synchronization data. Ex: hit type, hit origin, hit target, center of hit, weapon the bullet belongs to, etc, is the packet data.
  • ID_PLAYER_SYNC (207) = Responsible for on foot synchronization data. Ex: keys pressed, current position, health, armor, current weapon, speed, animations, surfing offsets, if the player is surfing some vehicle/object, special action, etc, is packet data.
Packet Types:
-Outcoming Packets: Packets sent by the server to the client.
-Incoming Packets: Packets sent by the client to the server.
Priorities:
-SYSTEM_PRIORITY: Internal Used by RakNet to send above-high priority messages.

-HIGH_PRIORITY: High priority messages are sent before medium priority messages.

-MEDIUM_PRIORITY: Medium priority messages are sent before low priority messages.

-LOW_PRIORITY: Low priority messages are only sent when no other messages are waiting.
Reliabilities:
-RELIABLE_SEQUENCED: Reliable sequenced packets are UDP packets monitored by a reliability layer to ensure they arrive at the destination and are sequenced at the destination.
Advantages - You get the reliability of UDP packets, the ordering of ordered packets, yet don't have to wait for old packets. More packets will arrive with this method than with the unreliable sequenced method, and they will be distributed more evenly. The most important advantage however is that the latest packet sent will arrive, where with unreliable sequenced the latest packet sent may not arrive.
Disadvantages - Wasteful of bandwidth because it uses the overhead of reliable UDP packets to ensure late packets arrive that just get ignored anyway.

-RELIABLE_ORDERED: Reliable ordered packets are UDP packets monitored by a reliability layer to ensure they arrive at the destination and are ordered at the destination. Advantages - The packet will get there and in the order it was sent. These are by far the easiest to program for because you don't have to worry about strange behavior due to out of order or lost packets.
Disadvantages - Retransmissions and acknowledgments can add significant bandwidth requirements. Packets may arrive very late if the network is busy. One late packet can delay many packets that arrived sooner, resulting in significant lag spikes. However, this disadvantage can be mitigated by the clever use of ordering streams .

-RELIABLE: Reliable packets are UDP packets monitored by a reliablilty layer to ensure they arrive at the destination.
Advantages - You know the packet will get there. Eventually...
Disadvantages - Retransmissions and acknowledgments can add significant bandwidth requirements. Packets may arrive very late if the network is busy. No packet ordering.

-UNRELIABLE_SEQUENCED: Unreliable sequenced packets are the same as unreliable packets, except that only the newest packet is ever accepted. Older packets are ignored. Advantages - Same low overhead as unreliable packets, and you don't have to worry about older packets changing your data to old values.
Disadvantages - A LOT of packets will be dropped since they may never arrive because of UDP and may be dropped even when they do arrive. These packets are the first to get dropped if the send buffer is full. The last packet sent may never arrive, which can be a problem if you stop sending packets at some particular point.

-UNRELIABLE: Unreliable packets are sent by straight UDP. They may arrive out of order, or not at all. This is best for data that is unimportant, or data that you send very frequently so even if some packets are missed newer packets will compensate.
Advantages - These packets don't need to be acknowledged by the network, saving the size of a UDP header in acknowledgment (about 50 bytes or so). The savings can really add up.
Disadvantages - No packet ordering, packets may never arrive, these packets are the first to get dropped if the send buffer is full.
• What is BitStream?
The BitStream class is a helper class in RakNet library that is used to wrap a dynamic array for the purpose of packing and unpacking bits.
• Modifying packet data
PHP Code:
#define ID_PLAYER_SYNC  207
public OnIncomingPacket(playeridpacketidBitStream:bs)
{
    if (
packetid == ID_PLAYER_SYNC)
    {
        new 
onFootData[PR_OnFootSync];
        
BS_IgnoreBits(bs8);
        
BS_ReadOnFootSync(bsonFootData);
        
onFootData[PR_weaponId] = 38;
        
BS_SetWriteOffset(bs8);
        
BS_WriteOnFootSync(bsonFootData);
    }
    return 
1;

In the example above, we modify the player's current weapon in the packet, thus making everyone see them holding a minigun (38).

BS_IgnoreBits(bs, 8); - Before reading the packet data, we ignore the first 8 bits (1 byte) because they contain the packet identifier.

BS_ReadOnFootSync(bs, onFootData); - After ignoring the first 8 bits, we can read the packet, which will have its data passed to onFootData (referencing the enumerator PR_OnFootSync).

onFootData[PR_weaponId] = 38; - We change the weapon id in the packet to anything we want. The id we set will be the one sent in the packet, and it will be the weapon other players will see.

BS_SetWriteOffset(bs, 8); - We set the write offset after the 8 bits, because we don't want to write over the packet identifier.

BS_WriteOnFootSync(bs, onFootData); - Then, we write the new on foot synchronization data in the BitStream.

return 1; - We return 1, allowing the packet to be sent with the new data we wrote in the BitStream.
• Sending a packet
To send a packet, we have to write it's data in a BitStream, the first parameter being it's identifier.

PHP Code:
#define ID_BULLET_SYNC  206
SendBullet(fromtodata[PR_BulletSync])
{
    new 
BitStream:bs BS_New();
    
BS_WriteValue(
        
bs,
        
PR_UINT8ID_BULLET_SYNC,
        
PR_UINT16from
    
);
    
BS_WriteBulletSync(bsdata);
    
BS_Send(bstoPR_HIGH_PRIORITYPR_RELIABLE_ORDERED);
    
BS_Delete(bs);
}
/*Somewhere in your code*/
new bulletData[PR_BulletSync];
bulletData[PR_hitType] = /*Your hit type*/;
bulletData[PR_hitId] = /*hit id*/;
bulletData[PR_origin][0] = /*origin X*/;
bulletData[PR_origin][1] = /*origin Y*/;
bulletData[PR_origin][2] = /*origin Z*/;
    
bulletData[PR_hitPos][0] = /*hit position X*/;
bulletData[PR_hitPos][1] = /*hit position Y*/;
bulletData[PR_hitPos][2] = /*hit position Z*/;
    
bulletData[PR_offsets][0] = /*offset X*/;
bulletData[PR_offsets][1] = /*offset Y*/;
bulletData[PR_offsets][2] = /*offset Z*/;
    
bulletData[PR_weaponId] = /*weapon id*/;
    
SendBulletData(01bulletData); 
In the example above, the function sends a packet with bullet data to a specific player.

new BitStream:bs = BS_New(); - We create a new BitStream, where we are going to write our packet data.

PR_UINT8, ID_BULLET_SYNC, - First parameter of the BitStream. That is the packet identifier.

PR_UINT16, from - Second parameter of the BitStream. This is the responsible player, from whom the bullet data will originate.

BS_WriteBulletSync(bs, data); - "data" references the enumerator PR_BulletSync and contains the bullet data we send in the function's 3rd parameter, it's data will be written in the BitStream.

BS_Send(bs, to, PR_HIGH_PRIORITY, PR_RELIABLE_ORDERED); - "to" is the player about to receive the packet. If "to" is -1, all players will receive the packet. PR_HIGH_PRIORITY is the packet's priority, and PR_RELIABLE_ORDERED is it's reliability.

BS_Delete(bs); - After we are done, we remove the BitStream.
Reply
#2

Good Job!

Well explained!
Reply
#3

This needs more appreciation and attention from the community, definitely one of those useful tutorials.
Reply
#4

This can detect some cleo name tag ?
Reply
#5

Quote:
Originally Posted by bigtigerbeee
View Post
This can detect some cleo name tag ?
Yes.
Reply
#6

Quote:
Originally Posted by RogueDrifter
View Post
Quote:
Originally Posted by bigtigerbeee
View Post
This can detect some cleo name tag ?
Yes.
No, obviously not. It is not like that information comes in the sync packets
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)