107 std::vector<std::uint8_t>
data;
217 inline std::vector<std::uint8_t>
serializeEvents(
const std::vector<EventRecord> &events)
219 std::vector<std::uint8_t> payload;
222 for (
const auto &ev : events)
224 const std::uint8_t dataLen =
static_cast<std::uint8_t
>(ev.data.size());
227 payload.push_back(
static_cast<std::uint8_t
>(ev.type));
230 payload.push_back(
static_cast<std::uint8_t
>((ev.entityId >> 24) & 0xFF));
231 payload.push_back(
static_cast<std::uint8_t
>((ev.entityId >> 16) & 0xFF));
232 payload.push_back(
static_cast<std::uint8_t
>((ev.entityId >> 8) & 0xFF));
233 payload.push_back(
static_cast<std::uint8_t
>(ev.entityId & 0xFF));
236 payload.push_back(dataLen);
239 payload.insert(payload.end(), ev.data.begin(), ev.data.end());
243 throw std::runtime_error(
"Events payload exceeds MAX_PAYLOAD");
253 inline std::vector<EventRecord>
deserializeEvents(
const std::uint8_t *payload,
const std::size_t length)
255 std::vector<EventRecord> events;
256 std::size_t offset = 0;
258 while (offset < length)
260 if (length - offset < 6)
262 throw std::runtime_error(
"Truncated event header in payload");
266 const std::uint32_t entityId = (
static_cast<std::uint32_t
>(payload[offset + 1]) << 24) |
267 (
static_cast<std::uint32_t
>(payload[offset + 2]) << 16) |
268 (
static_cast<std::uint32_t
>(payload[offset + 3]) << 8) |
269 static_cast<std::uint32_t
>(payload[offset + 4]);
270 const std::uint8_t dataLen = payload[offset + 5];
273 if (length - offset < dataLen)
275 throw std::runtime_error(
"Truncated event data in payload");
281 rec.
data.insert(rec.data.end(), payload + offset, payload + offset + dataLen);
283 events.emplace_back(std::move(rec));
294 std::vector<uint8_t> buffer(16);
296 buffer[0] = header.
type;
299 buffer[1] =
static_cast<uint8_t
>((header.
length >> 8) & 0xFF);
300 buffer[2] =
static_cast<uint8_t
>(header.
length & 0xFF);
303 buffer[3] =
static_cast<uint8_t
>((header.
flags >> 8) & 0xFF);
304 buffer[4] =
static_cast<uint8_t
>(header.
flags & 0xFF);
307 buffer[5] =
static_cast<uint8_t
>((header.
reserved >> 8) & 0xFF);
308 buffer[6] =
static_cast<uint8_t
>(header.
reserved & 0xFF);
311 buffer[7] =
static_cast<uint8_t
>((header.
sequence >> 24) & 0xFF);
312 buffer[8] =
static_cast<uint8_t
>((header.
sequence >> 16) & 0xFF);
313 buffer[9] =
static_cast<uint8_t
>((header.
sequence >> 8) & 0xFF);
314 buffer[10] =
static_cast<uint8_t
>(header.
sequence & 0xFF);
317 buffer[11] =
static_cast<uint8_t
>((header.
sessionId >> 24) & 0xFF);
318 buffer[12] =
static_cast<uint8_t
>((header.
sessionId >> 16) & 0xFF);
319 buffer[13] =
static_cast<uint8_t
>((header.
sessionId >> 8) & 0xFF);
320 buffer[14] =
static_cast<uint8_t
>(header.
sessionId & 0xFF);
334 if (payload && header.
length > 0)
336 buffer.insert(buffer.end(), payload, payload + header.
length);
349 throw std::runtime_error(
"Buffer too small for header");
354 header.
type = data[0];
357 header.
length = (
static_cast<std::uint16_t
>(data[1]) << 8) |
static_cast<std::uint16_t
>(data[2]);
360 header.
flags = (
static_cast<std::uint16_t
>(data[3]) << 8) |
static_cast<std::uint16_t
>(data[4]);
363 header.
reserved = (
static_cast<std::uint16_t
>(data[5]) << 8) |
static_cast<std::uint16_t
>(data[6]);
366 header.
sequence = (
static_cast<std::uint32_t
>(data[7]) << 24) | (
static_cast<std::uint32_t
>(data[8]) << 16) |
367 (
static_cast<std::uint32_t
>(data[9]) << 8) |
static_cast<std::uint32_t
>(data[10]);
370 header.
sessionId = (
static_cast<std::uint32_t
>(data[11]) << 24) | (
static_cast<std::uint32_t
>(data[12]) << 16) |
371 (
static_cast<std::uint32_t
>(data[13]) << 8) |
static_cast<std::uint32_t
>(data[14]);
EventType
Event types for ENTITY_EVENT packets.
std::vector< uint8_t > serializeHeader(const PacketHeader &header)
Serialize packet header (Big Endian as per RNP spec)
PacketFlags
Packet flags for reliability and fragmentation.
DisconnectReason
Disconnect reason codes.
EntityType
Entity types for world state.
PacketType
Packet types according to RNP specification.
std::vector< uint8_t > serialize(const PacketHeader &header, const uint8_t *payload=nullptr)
Serialize packet with header and optional payload (Big Endian)
PacketHeader deserializeHeader(const uint8_t *data, const std::size_t size)
Deserialize packet header (Big Endian)
std::vector< EventRecord > deserializeEvents(const std::uint8_t *payload, const std::size_t length)
Deserialize ENTITY_EVENT payload into event records Format per event: type(1) | entity_id(4,...
constexpr std::uint8_t PROTOCOL_VERSION
constexpr std::size_t MAX_PAYLOAD
std::vector< std::uint8_t > serializeEvents(const std::vector< EventRecord > &events)
Serialize events in ENTITY_EVENT format (TLV with entity_id) Format per event: type(1) | entity_id(4,...
Entity state for WORLD_STATE packet.
Event record for ENTITY_EVENT packets (TLV format)
std::vector< std::uint8_t > data
std::uint32_t cumulativeAck
CONNECT_ACCEPT packet payload.
std::uint16_t mtuPayloadBytes
DISCONNECT packet payload.
PING/PONG packet payload.
WORLD_STATE packet payload.
std::uint16_t entityCount
std::vector< EntityState > entities