Packet Structure

From JFTSE Wiki
Revision as of 15:23, 16 March 2026 by XxharCs (talk | contribs)
Jump to navigation Jump to search

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.

dataLength = 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.