Packet Structure: Difference between revisions

From JFTSE Wiki
Jump to navigation Jump to search
Created page with "= Packet Structure = All communication between the client and server uses a binary packet format. Each packet consists of a fixed 8 byte header (metadata) followed by a variable length payload. == Packet Layout == <pre> Offset Size Field 0x00 2 checkSerial 0x02 2 checkSum 0x04 2 packetId 0x06 2 dataLength 0x08 n data (payload) </pre> == Header Fields == {| class="wikitable" ! Field ! Size ! Description |- | checkSeri..."
 
No edit summary
 
(One intermediate revision by the same user not shown)
Line 9: Line 9:
<pre>
<pre>
Offset  Size  Field
Offset  Size  Field
0x00    2      checkSerial
0x00    2      serialnum
0x02    2      checkSum
0x02    2      checksum
0x04    2      packetId
0x04    2      packet id
0x06    2      dataLength
0x06    2      data length
0x08    n      data (payload)
0x08    n      data (payload)
</pre>
</pre>
Line 23: Line 23:
! Description
! Description
|-
|-
| checkSerial
| serialnum
| 2 bytes
| 2 bytes
| Serial value used by the protocol for packet validation and sequencing.
| Serial value used by the protocol for packet validation and sequencing.
|-
|-
| checkSum
| checksum
| 2 bytes
| 2 bytes
| Checksum used by the protocol to verify packet integrity.
| Checksum used by the protocol to verify packet integrity.
|-
|-
| packetId
| packet id
| 2 bytes
| 2 bytes
| Identifier that determines the packet type and how the payload should be interpreted.
| Identifier that determines the packet type and how the payload should be interpreted.
|-
|-
| dataLength
| data length
| 2 bytes
| 2 bytes
| Length of the payload (data) in bytes.
| Length of the payload (data) in bytes.
Line 45: Line 45:


<pre>
<pre>
dataLength = number of bytes following the header
data length = number of bytes following the header
</pre>
</pre>


Line 81: Line 81:


<pre>
<pre>
B8 79 -> checkSerial
B8 79 -> serialnum
BF 07 -> checkSum
BF 07 -> checksum
3F 18 -> packetId (0x183F)
3F 18 -> packet id (0x183F)
04 00 -> dataLength (4 bytes)
04 00 -> data length (4 bytes)
</pre>
</pre>


Line 121: Line 121:
From the packet metadata:
From the packet metadata:


* packetId = '''0x183F'''
* packet id = '''0x183F'''
* payload length = '''4 bytes'''
* payload length = '''4 bytes'''


Line 162: Line 162:


     String toString();
     String toString();
    // must be implemented by the concrete class for field deserialization
    static <T extends IPacket> T fromBytes(byte[] packet) {
        throw new UnsupportedOperationException("fromBytes method not implemented");
    }


}
}
Line 167: Line 172:


This interface defines the minimal contract required for packet serialization and metadata access.
This interface defines the minimal contract required for packet serialization and metadata access.
<code>fromBytes(payload)</code> is called by the Packet Deserializer, a registered packet class must implement it.
=== Example ===
Example implementation for CMSG_AuthLogin (auto-generated).
<syntaxhighlight lang="java">
public static CMSGAuthLogin fromBytes(byte[] rawData) {
    CMSGAuthLogin msg = new CMSGAuthLogin();
    ByteBuffer buffer = ByteBuffer.wrap(rawData).order(ByteOrder.nativeOrder());
    msg.metaData.checkSerial = buffer.getChar(0);
    msg.metaData.checkSum = buffer.getChar(2);
    msg.metaData.packetId = buffer.getChar(4);
    msg.metaData.dataLen = buffer.getChar(6);
    msg.data = new byte[msg.metaData.dataLen];
    BitKit.blockCopy(rawData, 8, msg.data, 0, msg.metaData.dataLen);
    msg.username = msg.readString();
    msg.token = msg.readFixedString(16);
    msg.timestamp = msg.readLong();
    return msg;
}
</syntaxhighlight>
== Packet Schema ==
Packet structures themselves are defined using the '''[[Packet Schema (.packet) Format]]'''. 
These schema files describe the payload layout for each packet id and are used to generate the corresponding packet classes automatically.


[[Category:Server]]
[[Category:Server]]
[[Category:Protocol]]
[[Category:Protocol]]

Latest revision as of 15:24, 16 March 2026

Packet Structure

All communication between the client and server uses a binary packet format.

Each packet consists of a fixed 8 byte header (metadata) followed by a variable length payload.

Packet Layout

Offset   Size   Field
0x00     2      serialnum
0x02     2      checksum
0x04     2      packet id
0x06     2      data length
0x08     n      data (payload)

Header Fields

Field Size Description
serialnum 2 bytes Serial value used by the protocol for packet validation and sequencing.
checksum 2 bytes Checksum used by the protocol to verify packet integrity.
packet id 2 bytes Identifier that determines the packet type and how the payload should be interpreted.
data length 2 bytes Length of the payload (data) in bytes.

Payload

The payload immediately follows the header and contains packet specific data.

data length = number of bytes following the header

The structure of the payload depends entirely on the packetId.


The maximum packet size is limited to 16384 bytes. Since the packet header has a fixed size of 8 bytes, the remaining 16376 bytes are available for payload data.

Maximum packet size : 16384 bytes
Header size         : 8 bytes
Maximum payload     : 16376 bytes

Example Packet

The following packet was captured from the server while processing a point update during a match.

2026-03-16 14:57:47,231 [epollEventLoopGroup-3-2] PacketLogger [decode] DEBUG RECV [12 bytes]
CMSGPoint { "id": "0x183F", "len": 4, "data": { "pointsTeam": 1, "unk0": 0, "ballState": 4, "playerPosition": 10 } }

--- Hex Dump ---
B8 79 BF 07 3F 18 04 00    01 00 04 0A
===

The total packet size is 12 bytes:

  • 8 bytes header
  • 4 bytes payload

Header

B8 79 -> serialnum
BF 07 -> checksum
3F 18 -> packet id (0x183F)
04 00 -> data length (4 bytes)

Payload

01 00 04 0A

Which the packet parser interprets as:

Field Value Hex
pointsTeam 1 01
unk0 0 00
ballState 4 04
playerPosition 10 0A

Packet Interpretation

From the packet metadata:

  • packet id = 0x183F
  • payload length = 4 bytes

The server maps this packetId to the packet type:

CMSGPoint

The payload is then decoded according to the structure defined for that packet type.

Byte Order

All packet fields are encoded using little-endian byte order.

Example:

17 00 -> 0x0017 -> 23

Packet Interface Contract

All packets in the server implementation follow the IPacket interface.

package com.jftse.server.core.protocol;

public interface IPacket {

    byte[] toBytes();

    char getDataLength();

    char getPacketId();

    char getCheckSerial();

    char getCheckSum();

    String toString();

    // must be implemented by the concrete class for field deserialization
    static <T extends IPacket> T fromBytes(byte[] packet) {
        throw new UnsupportedOperationException("fromBytes method not implemented");
    }

}

This interface defines the minimal contract required for packet serialization and metadata access.

fromBytes(payload) is called by the Packet Deserializer, a registered packet class must implement it.

Example

Example implementation for CMSG_AuthLogin (auto-generated).

public static CMSGAuthLogin fromBytes(byte[] rawData) {
    CMSGAuthLogin msg = new CMSGAuthLogin();
    ByteBuffer buffer = ByteBuffer.wrap(rawData).order(ByteOrder.nativeOrder());

    msg.metaData.checkSerial = buffer.getChar(0);
    msg.metaData.checkSum = buffer.getChar(2);
    msg.metaData.packetId = buffer.getChar(4);
    msg.metaData.dataLen = buffer.getChar(6);

    msg.data = new byte[msg.metaData.dataLen];
    BitKit.blockCopy(rawData, 8, msg.data, 0, msg.metaData.dataLen);

    msg.username = msg.readString();
    msg.token = msg.readFixedString(16);
    msg.timestamp = msg.readLong();
    return msg;
}

Packet Schema

Packet structures themselves are defined using the Packet Schema (.packet) Format. These schema files describe the payload layout for each packet id and are used to generate the corresponding packet classes automatically.