r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
Serializer.hpp
Go to the documentation of this file.
1///
2/// @file Serializer.hpp
3/// @brief Network packet serializer for RNP protocol
4/// @namespace rnp
5///
6
7#pragma once
8
9#include "Protocol.hpp"
10#include <algorithm>
11#include <cstring>
12#include <stdexcept>
13#include <vector>
14
15namespace rnp
16{
17
18 ///
19 /// @brief Utility class for endianness conversion
20 ///
22 {
23 public:
24 static std::uint16_t hostToNetwork16(std::uint16_t hostValue)
25 {
26 return ((hostValue & 0xFF00) >> 8) | ((hostValue & 0x00FF) << 8);
27 }
28
29 static std::uint32_t hostToNetwork32(std::uint32_t hostValue)
30 {
31 return ((hostValue & 0xFF000000) >> 24) | ((hostValue & 0x00FF0000) >> 8) |
32 ((hostValue & 0x0000FF00) << 8) | ((hostValue & 0x000000FF) << 24);
33 }
34
35 static float hostToNetworkFloat(float hostValue)
36 {
37 std::uint32_t intValue;
38 std::memcpy(&intValue, &hostValue, sizeof(float));
39 intValue = hostToNetwork32(intValue);
40 float result;
41 std::memcpy(&result, &intValue, sizeof(float));
42 return result;
43 }
44
45 static std::uint16_t networkToHost16(std::uint16_t networkValue)
46 {
47 return hostToNetwork16(networkValue); // Same operation for 16-bit
48 }
49
50 static std::uint32_t networkToHost32(std::uint32_t networkValue)
51 {
52 return hostToNetwork32(networkValue); // Same operation for 32-bit
53 }
54
55 static float networkToHostFloat(float networkValue)
56 {
57 return hostToNetworkFloat(networkValue); // Same operation for float
58 }
59 };
60
61 ///
62 /// @brief Binary serializer for RNP protocol packets
63 ///
65 {
66 private:
67 std::vector<std::uint8_t> buffer_;
68 std::size_t writePos_;
69 std::size_t readPos_;
70
71 public:
72 ///
73 /// @brief Constructor
74 ///
76 {
77 // PacketHeader serialized size: 1 (type) + 2 (length) + 4 (sessionId) = 7 bytes
78 constexpr std::size_t PACKET_HEADER_SIZE = 7;
79 buffer_.reserve(MAX_PAYLOAD + PACKET_HEADER_SIZE);
80 }
81
82 ///
83 /// @brief Constructor with initial capacity
84 /// @param capacity Initial buffer capacity
85 ///
86 explicit Serializer(std::size_t capacity) : writePos_(0), readPos_(0) { buffer_.reserve(capacity); }
87
88 ///
89 /// @brief Constructor from existing data
90 /// @param data Existing data to deserialize
91 ///
92 explicit Serializer(const std::vector<std::uint8_t> &data)
93 : buffer_(data), writePos_(data.size()), readPos_(0)
94 {
95 }
96
97 ///
98 /// @brief Reset the serializer for reuse
99 ///
100 void reset()
101 {
102 buffer_.clear();
103 writePos_ = 0;
104 readPos_ = 0;
105 }
106
107 ///
108 /// @brief Get the serialized data
109 /// @return Vector containing the serialized bytes
110 ///
111 const std::vector<std::uint8_t> &getData() const { return buffer_; }
112
113 ///
114 /// @brief Get the current size of serialized data
115 /// @return Size in bytes
116 ///
117 std::size_t getSize() const { return writePos_; }
118
119 ///
120 /// @brief Write raw bytes
121 /// @param data Pointer to data
122 /// @param size Number of bytes to write
123 ///
124 void writeBytes(const void *data, std::size_t size)
125 {
126 // PacketHeader serialized size: 1 (type) + 2 (length) + 4 (sessionId) = 7 bytes
127 constexpr std::size_t PACKET_HEADER_SIZE = 7;
128 if (writePos_ + size > MAX_PAYLOAD + PACKET_HEADER_SIZE)
129 {
130 throw std::runtime_error("Serializer buffer overflow");
131 }
132
133 buffer_.resize(writePos_ + size);
134 std::memcpy(buffer_.data() + writePos_, data, size);
135 writePos_ += size;
136 }
137
138 ///
139 /// @brief Write a single byte
140 /// @param value Byte value to write
141 ///
142 void writeByte(std::uint8_t value) { writeBytes(&value, sizeof(value)); }
143
144 ///
145 /// @brief Write a 16-bit integer (network byte order)
146 /// @param value 16-bit integer to write
147 ///
148 void writeUInt16(std::uint16_t value)
149 {
150 std::uint16_t networkValue = EndianUtils::hostToNetwork16(value);
151 writeBytes(&networkValue, sizeof(networkValue));
152 }
153
154 ///
155 /// @brief Write a 32-bit integer (network byte order)
156 /// @param value 32-bit integer to write
157 ///
158 void writeUInt32(std::uint32_t value)
159 {
160 std::uint32_t networkValue = EndianUtils::hostToNetwork32(value);
161 writeBytes(&networkValue, sizeof(networkValue));
162 }
163
164 ///
165 /// @brief Write a float (network byte order)
166 /// @param value Float to write
167 ///
168 void writeFloat(float value)
169 {
170 float networkValue = EndianUtils::hostToNetworkFloat(value);
171 writeBytes(&networkValue, sizeof(networkValue));
172 }
173
174 ///
175 /// @brief Write a string with length prefix
176 /// @param str String to write
177 /// @param maxLength Maximum allowed length
178 ///
179 void writeString(const std::string &str, std::size_t maxLength)
180 {
181 if (str.length() > maxLength)
182 {
183 throw std::runtime_error("String too long for serialization");
184 }
185
186 writeByte(static_cast<std::uint8_t>(str.length()));
187 if (!str.empty())
188 {
189 writeBytes(str.data(), str.length());
190 }
191 }
192
193 ///
194 /// @brief Read raw bytes
195 /// @param data Pointer to destination buffer
196 /// @param size Number of bytes to read
197 ///
198 void readBytes(void *data, std::size_t size)
199 {
200 if (readPos_ + size > buffer_.size())
201 {
202 throw std::runtime_error("Serializer buffer underflow");
203 }
204
205 std::memcpy(data, buffer_.data() + readPos_, size);
206 readPos_ += size;
207 }
208
209 ///
210 /// @brief Read a single byte
211 /// @return Byte value
212 ///
213 std::uint8_t readByte()
214 {
215 std::uint8_t value;
216 readBytes(&value, sizeof(value));
217 return value;
218 }
219
220 ///
221 /// @brief Read a 16-bit integer (network byte order)
222 /// @return 16-bit integer in host byte order
223 ///
224 std::uint16_t readUInt16()
225 {
226 std::uint16_t networkValue;
227 readBytes(&networkValue, sizeof(networkValue));
228 return EndianUtils::networkToHost16(networkValue);
229 }
230
231 ///
232 /// @brief Read a 32-bit integer (network byte order)
233 /// @return 32-bit integer in host byte order
234 ///
235 std::uint32_t readUInt32()
236 {
237 std::uint32_t networkValue;
238 readBytes(&networkValue, sizeof(networkValue));
239 return EndianUtils::networkToHost32(networkValue);
240 }
241
242 ///
243 /// @brief Read a float (network byte order)
244 /// @return Float in host byte order
245 ///
246 float readFloat()
247 {
248 float networkValue;
249 readBytes(&networkValue, sizeof(networkValue));
250 return EndianUtils::networkToHostFloat(networkValue);
251 }
252
253 ///
254 /// @brief Read a string with length prefix
255 /// @param maxLength Maximum expected length
256 /// @return The read string
257 ///
258 std::string readString(std::size_t maxLength)
259 {
260 std::uint8_t length = readByte();
261 if (length > maxLength)
262 {
263 throw std::runtime_error("String length exceeds maximum");
264 }
265
266 if (length == 0)
267 {
268 return std::string();
269 }
270
271 std::string result(length, '\0');
272 readBytes(result.data(), length);
273 return result;
274 }
275
276 ///
277 /// @brief Serialize packet header
278 /// @param header Header to serialize
279 ///
280 void serializeHeader(const PacketHeader &header)
281 {
282 writeByte(header.type);
283 writeUInt16(header.length);
284 writeUInt32(header.sessionId);
285 }
286
287 ///
288 /// @brief Deserialize packet header
289 /// @return Deserialized header
290 ///
292 {
293 PacketHeader header;
294 header.type = readByte();
295 header.length = readUInt16();
296 header.sessionId = readUInt32();
297 return header;
298 }
299
300 ///
301 /// @brief Serialize CONNECT packet
302 /// @param packet CONNECT packet to serialize
303 ///
304 void serializeConnect(const PacketConnect &packet)
305 {
306 writeByte(packet.nameLen);
307 writeBytes(packet.playerName.data(), packet.playerName.size());
308 writeUInt32(packet.clientCaps);
309 }
310
311 ///
312 /// @brief Deserialize CONNECT packet
313 /// @return Deserialized CONNECT packet
314 ///
316 {
317 PacketConnect packet;
318 packet.nameLen = readByte();
319 readBytes(packet.playerName.data(), packet.playerName.size());
320 packet.clientCaps = readUInt32();
321 return packet;
322 }
323
324 ///
325 /// @brief Serialize CONNECT_ACCEPT packet
326 /// @param packet CONNECT_ACCEPT packet to serialize
327 ///
329 {
330 writeUInt32(packet.sessionId);
331 writeUInt16(packet.tickRateHz);
333 writeUInt32(packet.serverCaps);
334 }
335
336 ///
337 /// @brief Deserialize CONNECT_ACCEPT packet
338 /// @return Deserialized CONNECT_ACCEPT packet
339 ///
341 {
342 PacketConnectAccept packet;
343 packet.sessionId = readUInt32();
344 packet.tickRateHz = readUInt16();
345 packet.mtuPayloadBytes = readUInt16();
346 packet.serverCaps = readUInt32();
347 return packet;
348 }
349
350 ///
351 /// @brief Serialize DISCONNECT packet
352 /// @param packet DISCONNECT packet to serialize
353 ///
355
356 ///
357 /// @brief Deserialize DISCONNECT packet
358 /// @return Deserialized DISCONNECT packet
359 ///
361 {
362 PacketDisconnect packet;
363 packet.reasonCode = readUInt16();
364 return packet;
365 }
366
367 ///
368 /// @brief Serialize EntityState
369 /// @param entity Entity state to serialize
370 ///
372 {
373 writeUInt32(entity.id);
374 writeUInt16(entity.type);
375 writeByte(entity.subtype);
376 writeFloat(entity.x);
377 writeFloat(entity.y);
378 writeFloat(entity.vx);
379 writeFloat(entity.vy);
380 writeByte(entity.healthPercent);
381 writeByte(entity.stateFlags);
382 writeUInt32(entity.score);
383 }
384
385 ///
386 /// @brief Deserialize EntityState
387 /// @return Deserialized entity state
388 ///
390 {
391 EntityState entity;
392 entity.id = readUInt32();
393 entity.type = readUInt16();
394 entity.subtype = readByte();
395 entity.x = readFloat();
396 entity.y = readFloat();
397 entity.vx = readFloat();
398 entity.vy = readFloat();
399 entity.healthPercent = readByte();
400 entity.stateFlags = readByte();
401 entity.score = readUInt32();
402 return entity;
403 }
404
405 ///
406 /// @brief Serialize WORLD_STATE packet
407 /// @param packet WORLD_STATE packet to serialize
408 ///
410 {
411 writeUInt32(packet.serverTick);
412 writeUInt16(packet.entityCount);
413
414 for (const auto &entity : packet.entities)
415 {
416 serializeEntityState(entity);
417 }
418 }
419
420 ///
421 /// @brief Deserialize WORLD_STATE packet
422 /// @return Deserialized WORLD_STATE packet
423 ///
425 {
426 PacketWorldState packet;
427 packet.serverTick = readUInt32();
428 packet.entityCount = readUInt16();
429
430 packet.entities.reserve(packet.entityCount);
431 for (std::uint16_t i = 0; i < packet.entityCount; ++i)
432 {
433 packet.entities.push_back(deserializeEntityState());
434 }
435
436 return packet;
437 }
438
439 ///
440 /// @brief Serialize PING/PONG packet
441 /// @param packet PING/PONG packet to serialize
442 ///
444 {
445 writeUInt32(packet.nonce);
446 writeUInt32(packet.sendTimeMs);
447 }
448
449 ///
450 /// @brief Deserialize PING/PONG packet
451 /// @return Deserialized PING/PONG packet
452 ///
454 {
455 PacketPingPong packet;
456 packet.nonce = readUInt32();
457 packet.sendTimeMs = readUInt32();
458 return packet;
459 }
460
461 ///
462 /// @brief Serialize ERROR packet
463 /// @param packet ERROR packet to serialize
464 ///
465 void serializeError(const PacketError &packet)
466 {
467 writeUInt16(packet.errorCode);
468 writeUInt16(packet.msgLen);
469 if (!packet.description.empty())
470 {
471 writeBytes(packet.description.data(), packet.description.length());
472 }
473 }
474
475 ///
476 /// @brief Deserialize ERROR packet
477 /// @return Deserialized ERROR packet
478 ///
480 {
481 PacketError packet;
482 packet.errorCode = readUInt16();
483 packet.msgLen = readUInt16();
484
485 if (packet.msgLen > 0)
486 {
487 packet.description.resize(packet.msgLen);
488 readBytes(packet.description.data(), packet.msgLen);
489 }
490
491 return packet;
492 }
493
494 ///
495 /// @brief Serialize EventRecord for ENTITY_EVENT packets
496 /// @param event Event record to serialize
497 ///
499 {
500 writeByte(static_cast<std::uint8_t>(event.type));
501 writeUInt32(event.entityId);
502 writeUInt16(static_cast<std::uint16_t>(event.data.size()));
503
504 if (!event.data.empty())
505 {
506 writeBytes(event.data.data(), event.data.size());
507 }
508 }
509
510 ///
511 /// @brief Deserialize EventRecord from ENTITY_EVENT packets
512 /// @return Deserialized event record
513 ///
515 {
516 EventRecord event;
517 event.type = static_cast<EventType>(readByte());
518 event.entityId = readUInt32();
519
520 std::uint16_t dataLength = readUInt16();
521 if (dataLength > 0)
522 {
523 event.data.resize(dataLength);
524 readBytes(event.data.data(), dataLength);
525 }
526
527 return event;
528 }
529
530 ///
531 /// @brief Serialize multiple EventRecords for ENTITY_EVENT packet
532 /// @param events Vector of event records to serialize
533 ///
534 void serializeEntityEvents(const std::vector<EventRecord> &events)
535 {
536 for (const auto &event : events)
537 {
539 }
540 }
541
542 ///
543 /// @brief Deserialize multiple EventRecords from ENTITY_EVENT packet
544 /// @param payloadSize Total size of the payload to deserialize
545 /// @return Vector of deserialized event records
546 ///
547 std::vector<EventRecord> deserializeEntityEvents(std::size_t payloadSize)
548 {
549 std::vector<EventRecord> events;
550 std::size_t bytesRead = 0;
551
552 while (bytesRead < payloadSize && readPos_ < buffer_.size())
553 {
554 std::size_t startPos = readPos_;
556 bytesRead += (readPos_ - startPos);
557 events.push_back(event);
558 }
559
560 return events;
561 }
562
563 ///
564 /// @brief Serialize input data for INPUT events
565 /// @param keys Keyboard input bitmask
566 /// @param mouseX Mouse X position
567 /// @param mouseY Mouse Y position
568 /// @param mouseButtons Mouse button bitmask
569 /// @param timestamp Input timestamp
570 ///
571 void serializeInputData(std::uint8_t keys, float mouseX, float mouseY, std::uint8_t mouseButtons,
572 std::uint32_t timestamp)
573 {
574 writeByte(keys);
575 writeFloat(mouseX);
576 writeFloat(mouseY);
577 writeByte(mouseButtons);
578 writeUInt32(timestamp);
579 }
580
581 ///
582 /// @brief Deserialize input data from INPUT events
583 /// @param keys Output keyboard input bitmask
584 /// @param mouseX Output mouse X position
585 /// @param mouseY Output mouse Y position
586 /// @param mouseButtons Output mouse button bitmask
587 /// @param timestamp Output input timestamp
588 ///
589 void deserializeInputData(std::uint8_t &keys, float &mouseX, float &mouseY, std::uint8_t &mouseButtons,
590 std::uint32_t &timestamp)
591 {
592 keys = readByte();
593 mouseX = readFloat();
594 mouseY = readFloat();
595 mouseButtons = readByte();
596 timestamp = readUInt32();
597 }
598
599 ///
600 /// @brief Create an EventRecord for input data
601 /// @param entityId Player entity ID
602 /// @param keys Keyboard input
603 /// @param mouseX Mouse X
604 /// @param mouseY Mouse Y
605 /// @param mouseButtons Mouse buttons
606 /// @param timestamp Timestamp
607 /// @return EventRecord ready to send
608 ///
609 static EventRecord createInputEvent(std::uint32_t entityId, std::uint8_t keys, float mouseX, float mouseY,
610 std::uint8_t mouseButtons, std::uint32_t timestamp)
611 {
612 Serializer inputSerializer;
613 inputSerializer.serializeInputData(keys, mouseX, mouseY, mouseButtons, timestamp);
614
615 EventRecord event;
616 event.type = EventType::INPUT;
617 event.entityId = entityId;
618 event.data = inputSerializer.getData();
619
620 return event;
621 }
622
623 ///
624 /// @brief Create an EventRecord for spawn event
625 /// @param entityId Entity ID to spawn
626 /// @param entityType Type of entity
627 /// @param x X position
628 /// @param y Y position
629 /// @return EventRecord for spawn
630 ///
631 static EventRecord createSpawnEvent(std::uint32_t entityId, EntityType entityType, float x, float y)
632 {
633 Serializer spawnSerializer;
634 spawnSerializer.writeUInt16(static_cast<std::uint16_t>(entityType));
635 spawnSerializer.writeFloat(x);
636 spawnSerializer.writeFloat(y);
637
638 EventRecord event;
639 event.type = EventType::SPAWN;
640 event.entityId = entityId;
641 event.data = spawnSerializer.getData();
642
643 return event;
644 }
645
646 ///
647 /// @brief Create an EventRecord for damage event
648 /// @param entityId Entity taking damage
649 /// @param damage Amount of damage
650 /// @param sourceId Source entity causing damage
651 /// @return EventRecord for damage
652 ///
653 static EventRecord createDamageEvent(std::uint32_t entityId, std::uint32_t damage,
654 std::uint32_t sourceId = 0)
655 {
656 Serializer damageSerializer;
657 damageSerializer.writeUInt32(damage);
658 damageSerializer.writeUInt32(sourceId);
659
660 EventRecord event;
661 event.type = EventType::DAMAGE;
662 event.entityId = entityId;
663 event.data = damageSerializer.getData();
664
665 return event;
666 }
667
668 ///
669 /// @brief Create an EventRecord for score event
670 /// @param entityId Entity gaining score
671 /// @param score Score amount
672 /// @return EventRecord for score
673 ///
674 static EventRecord createScoreEvent(std::uint32_t entityId, std::uint32_t score)
675 {
676 Serializer scoreSerializer;
677 scoreSerializer.writeUInt32(score);
678
679 EventRecord event;
680 event.type = EventType::SCORE;
681 event.entityId = entityId;
682 event.data = scoreSerializer.getData();
683
684 return event;
685 }
686
687 ///
688 /// @brief Create an EventRecord for despawn event
689 /// @param entityId Entity to despawn
690 /// @return EventRecord for despawn
691 ///
692 EventRecord createDespawnEvent(std::uint32_t entityId)
693 {
694 EventRecord event;
695 event.type = EventType::DESPAWN;
696 event.entityId = entityId;
697 return event;
698 }
699
700 ///
701 /// @brief Serialize LobbyInfo structure
702 /// @param lobbyInfo The lobby info to serialize
703 ///
704 void serializeLobbyInfo(const LobbyInfo &lobbyInfo)
705 {
706 writeUInt32(lobbyInfo.lobbyId);
707 writeBytes(reinterpret_cast<const std::uint8_t *>(lobbyInfo.lobbyName.data()),
708 lobbyInfo.lobbyName.size());
709 writeByte(lobbyInfo.currentPlayers);
710 writeByte(lobbyInfo.maxPlayers);
711 writeByte(lobbyInfo.gameMode);
712 writeByte(lobbyInfo.status);
713 writeUInt32(lobbyInfo.hostSessionId);
714
715 // Serialize player names array
716 for (const auto &playerName : lobbyInfo.playerNames)
717 {
718 writeBytes(reinterpret_cast<const std::uint8_t *>(playerName.data()), playerName.size());
719 }
720 }
721
722 ///
723 /// @brief Deserialize LobbyInfo structure
724 /// @return Deserialized lobby info
725 ///
727 {
728 LobbyInfo lobbyInfo;
729 lobbyInfo.lobbyId = readUInt32();
730 readBytes(reinterpret_cast<std::uint8_t *>(lobbyInfo.lobbyName.data()), lobbyInfo.lobbyName.size());
731 lobbyInfo.currentPlayers = readByte();
732 lobbyInfo.maxPlayers = readByte();
733 lobbyInfo.gameMode = readByte();
734 lobbyInfo.status = readByte();
735 lobbyInfo.hostSessionId = readUInt32();
736
737 // Deserialize player names array
738 for (auto &playerName : lobbyInfo.playerNames)
739 {
740 readBytes(reinterpret_cast<std::uint8_t *>(playerName.data()), playerName.size());
741 }
742
743 return lobbyInfo;
744 }
745
746 ///
747 /// @brief Serialize LOBBY_LIST_RESPONSE packet
748 /// @param packet The packet to serialize
749 ///
751 {
752 writeUInt16(packet.lobbyCount);
753 for (const auto &lobby : packet.lobbies)
754 {
755 serializeLobbyInfo(lobby);
756 }
757 }
758
759 ///
760 /// @brief Deserialize LOBBY_LIST_RESPONSE packet
761 /// @return Deserialized packet
762 ///
764 {
766 packet.lobbyCount = readUInt16();
767 packet.lobbies.reserve(packet.lobbyCount);
768
769 for (std::uint16_t i = 0; i < packet.lobbyCount; ++i)
770 {
771 packet.lobbies.push_back(deserializeLobbyInfo());
772 }
773
774 return packet;
775 }
776
777 ///
778 /// @brief Serialize LOBBY_CREATE packet
779 /// @param packet The packet to serialize
780 ///
782 {
783 writeByte(packet.nameLen);
784 writeBytes(reinterpret_cast<const std::uint8_t *>(packet.lobbyName.data()), packet.lobbyName.size());
785 writeByte(packet.maxPlayers);
786 writeByte(packet.gameMode);
787 }
788
789 ///
790 /// @brief Deserialize LOBBY_CREATE packet
791 /// @return Deserialized packet
792 ///
794 {
795 PacketLobbyCreate packet;
796 packet.nameLen = readByte();
797 readBytes(reinterpret_cast<std::uint8_t *>(packet.lobbyName.data()), packet.lobbyName.size());
798 packet.maxPlayers = readByte();
799 packet.gameMode = readByte();
800 return packet;
801 }
802
803 ///
804 /// @brief Serialize LOBBY_CREATE_RESPONSE packet
805 /// @param packet The packet to serialize
806 ///
808 {
809 writeUInt32(packet.lobbyId);
810 writeByte(packet.success);
811 writeUInt16(packet.errorCode);
812 }
813
814 ///
815 /// @brief Deserialize LOBBY_CREATE_RESPONSE packet
816 /// @return Deserialized packet
817 ///
819 {
821 packet.lobbyId = readUInt32();
822 packet.success = readByte();
823 packet.errorCode = readUInt16();
824 return packet;
825 }
826
827 ///
828 /// @brief Serialize LOBBY_JOIN packet
829 /// @param packet The packet to serialize
830 ///
831 void serializeLobbyJoin(const PacketLobbyJoin &packet) { writeUInt32(packet.lobbyId); }
832
833 ///
834 /// @brief Deserialize LOBBY_JOIN packet
835 /// @return Deserialized packet
836 ///
838 {
839 PacketLobbyJoin packet;
840 packet.lobbyId = readUInt32();
841 return packet;
842 }
843
844 ///
845 /// @brief Serialize LOBBY_JOIN_RESPONSE packet
846 /// @param packet The packet to serialize
847 ///
849 {
850 writeUInt32(packet.lobbyId);
851 writeByte(packet.success);
852 writeUInt16(packet.errorCode);
853 if (packet.success == 1)
854 {
856 }
857 }
858
859 ///
860 /// @brief Deserialize LOBBY_JOIN_RESPONSE packet
861 /// @return Deserialized packet
862 ///
864 {
866 packet.lobbyId = readUInt32();
867 packet.success = readByte();
868 packet.errorCode = readUInt16();
869 if (packet.success == 1)
870 {
872 }
873 return packet;
874 }
875
876 ///
877 /// @brief Serialize LOBBY_UPDATE packet
878 /// @param packet The packet to serialize
879 ///
881
882 ///
883 /// @brief Deserialize LOBBY_UPDATE packet
884 /// @return Deserialized packet
885 ///
887 {
888 PacketLobbyUpdate packet;
890 return packet;
891 }
892
893 ///
894 /// @brief Serialize GAME_START packet
895 /// @param packet The packet to serialize
896 ///
897 void serializeGameStart(const PacketGameStart &packet) { writeUInt32(packet.lobbyId); }
898
899 ///
900 /// @brief Deserialize GAME_START packet
901 /// @return Deserialized packet
902 ///
904 {
905 PacketGameStart packet;
906 packet.lobbyId = readUInt32();
907 return packet;
908 }
909
910 ///
911 /// @brief Serialize START_GAME_REQUEST packet
912 /// @param packet The packet to serialize
913 ///
915
916 ///
917 /// @brief Deserialize START_GAME_REQUEST packet
918 /// @return Deserialized packet
919 ///
921 {
923 packet.lobbyId = readUInt32();
924 return packet;
925 }
926 };
927
928} // namespace rnp
This file contains the network protocol.
Utility class for endianness conversion.
static std::uint16_t hostToNetwork16(std::uint16_t hostValue)
static std::uint16_t networkToHost16(std::uint16_t networkValue)
static float networkToHostFloat(float networkValue)
static std::uint32_t hostToNetwork32(std::uint32_t hostValue)
static std::uint32_t networkToHost32(std::uint32_t networkValue)
static float hostToNetworkFloat(float hostValue)
Binary serializer for RNP protocol packets.
EventRecord createDespawnEvent(std::uint32_t entityId)
Create an EventRecord for despawn event.
std::vector< EventRecord > deserializeEntityEvents(std::size_t payloadSize)
Deserialize multiple EventRecords from ENTITY_EVENT packet.
PacketStartGameRequest deserializeStartGameRequest()
Deserialize START_GAME_REQUEST packet.
void serializePingPong(const PacketPingPong &packet)
Serialize PING/PONG packet.
void reset()
Reset the serializer for reuse.
void serializeLobbyCreateResponse(const PacketLobbyCreateResponse &packet)
Serialize LOBBY_CREATE_RESPONSE packet.
void writeBytes(const void *data, std::size_t size)
Write raw bytes.
static EventRecord createDamageEvent(std::uint32_t entityId, std::uint32_t damage, std::uint32_t sourceId=0)
Create an EventRecord for damage event.
EntityState deserializeEntityState()
Deserialize EntityState.
void serializeLobbyInfo(const LobbyInfo &lobbyInfo)
Serialize LobbyInfo structure.
PacketLobbyJoinResponse deserializeLobbyJoinResponse()
Deserialize LOBBY_JOIN_RESPONSE packet.
std::vector< std::uint8_t > buffer_
PacketHeader deserializeHeader()
Deserialize packet header.
PacketConnect deserializeConnect()
Deserialize CONNECT packet.
void serializeLobbyListResponse(const PacketLobbyListResponse &packet)
Serialize LOBBY_LIST_RESPONSE packet.
void writeByte(std::uint8_t value)
Write a single byte.
void readBytes(void *data, std::size_t size)
Read raw bytes.
std::size_t readPos_
std::size_t writePos_
void writeString(const std::string &str, std::size_t maxLength)
Write a string with length prefix.
void serializeEntityState(const EntityState &entity)
Serialize EntityState.
void serializeStartGameRequest(const PacketStartGameRequest &packet)
Serialize START_GAME_REQUEST packet.
PacketLobbyUpdate deserializeLobbyUpdate()
Deserialize LOBBY_UPDATE packet.
void serializeWorldState(const PacketWorldState &packet)
Serialize WORLD_STATE packet.
PacketError deserializeError()
Deserialize ERROR packet.
void serializeHeader(const PacketHeader &header)
Serialize packet header.
PacketLobbyJoin deserializeLobbyJoin()
Deserialize LOBBY_JOIN packet.
LobbyInfo deserializeLobbyInfo()
Deserialize LobbyInfo structure.
static EventRecord createInputEvent(std::uint32_t entityId, std::uint8_t keys, float mouseX, float mouseY, std::uint8_t mouseButtons, std::uint32_t timestamp)
Create an EventRecord for input data.
PacketConnectAccept deserializeConnectAccept()
Deserialize CONNECT_ACCEPT packet.
void serializeConnectAccept(const PacketConnectAccept &packet)
Serialize CONNECT_ACCEPT packet.
PacketLobbyCreate deserializeLobbyCreate()
Deserialize LOBBY_CREATE packet.
static EventRecord createScoreEvent(std::uint32_t entityId, std::uint32_t score)
Create an EventRecord for score event.
PacketGameStart deserializeGameStart()
Deserialize GAME_START packet.
static EventRecord createSpawnEvent(std::uint32_t entityId, EntityType entityType, float x, float y)
Create an EventRecord for spawn event.
std::uint8_t readByte()
Read a single byte.
void writeUInt16(std::uint16_t value)
Write a 16-bit integer (network byte order)
Serializer()
Constructor.
void serializeLobbyCreate(const PacketLobbyCreate &packet)
Serialize LOBBY_CREATE packet.
void serializeConnect(const PacketConnect &packet)
Serialize CONNECT packet.
void serializeGameStart(const PacketGameStart &packet)
Serialize GAME_START packet.
PacketLobbyListResponse deserializeLobbyListResponse()
Deserialize LOBBY_LIST_RESPONSE packet.
PacketPingPong deserializePingPong()
Deserialize PING/PONG packet.
void writeUInt32(std::uint32_t value)
Write a 32-bit integer (network byte order)
void serializeDisconnect(const PacketDisconnect &packet)
Serialize DISCONNECT packet.
EventRecord deserializeEventRecord()
Deserialize EventRecord from ENTITY_EVENT packets.
PacketWorldState deserializeWorldState()
Deserialize WORLD_STATE packet.
void writeFloat(float value)
Write a float (network byte order)
std::uint16_t readUInt16()
Read a 16-bit integer (network byte order)
Serializer(std::size_t capacity)
Constructor with initial capacity.
void serializeLobbyJoinResponse(const PacketLobbyJoinResponse &packet)
Serialize LOBBY_JOIN_RESPONSE packet.
void deserializeInputData(std::uint8_t &keys, float &mouseX, float &mouseY, std::uint8_t &mouseButtons, std::uint32_t &timestamp)
Deserialize input data from INPUT events.
std::uint32_t readUInt32()
Read a 32-bit integer (network byte order)
std::string readString(std::size_t maxLength)
Read a string with length prefix.
const std::vector< std::uint8_t > & getData() const
Get the serialized data.
void serializeEntityEvents(const std::vector< EventRecord > &events)
Serialize multiple EventRecords for ENTITY_EVENT packet.
float readFloat()
Read a float (network byte order)
void serializeError(const PacketError &packet)
Serialize ERROR packet.
std::size_t getSize() const
Get the current size of serialized data.
void serializeEventRecord(const EventRecord &event)
Serialize EventRecord for ENTITY_EVENT packets.
PacketDisconnect deserializeDisconnect()
Deserialize DISCONNECT packet.
void serializeLobbyJoin(const PacketLobbyJoin &packet)
Serialize LOBBY_JOIN packet.
PacketLobbyCreateResponse deserializeLobbyCreateResponse()
Deserialize LOBBY_CREATE_RESPONSE packet.
Serializer(const std::vector< std::uint8_t > &data)
Constructor from existing data.
void serializeLobbyUpdate(const PacketLobbyUpdate &packet)
Serialize LOBBY_UPDATE packet.
void serializeInputData(std::uint8_t keys, float mouseX, float mouseY, std::uint8_t mouseButtons, std::uint32_t timestamp)
Serialize input data for INPUT events.
EventType
Event types for ENTITY_EVENT packets.
Definition Protocol.hpp:92
EntityType
Entity types for world state.
Definition Protocol.hpp:106
constexpr std::size_t MAX_PAYLOAD
Definition Protocol.hpp:18
Entity state for WORLD_STATE packet.
Definition Protocol.hpp:183
std::uint32_t id
Definition Protocol.hpp:184
std::uint16_t type
Definition Protocol.hpp:185
std::uint32_t score
Definition Protocol.hpp:191
std::uint8_t stateFlags
Definition Protocol.hpp:190
std::uint8_t healthPercent
Definition Protocol.hpp:189
std::uint8_t subtype
Definition Protocol.hpp:186
Event record for ENTITY_EVENT packets (TLV format)
Definition Protocol.hpp:117
std::uint32_t entityId
Definition Protocol.hpp:119
std::vector< std::uint8_t > data
Definition Protocol.hpp:120
Lobby information structure.
Definition Protocol.hpp:237
std::uint32_t hostSessionId
Definition Protocol.hpp:244
std::array< char, 32 > lobbyName
Definition Protocol.hpp:239
std::uint8_t status
Definition Protocol.hpp:243
std::array< std::array< char, 32 >, 8 > playerNames
Definition Protocol.hpp:245
std::uint32_t lobbyId
Definition Protocol.hpp:238
std::uint8_t currentPlayers
Definition Protocol.hpp:240
std::uint8_t maxPlayers
Definition Protocol.hpp:241
std::uint8_t gameMode
Definition Protocol.hpp:242
CONNECT_ACCEPT packet payload.
Definition Protocol.hpp:148
std::uint32_t sessionId
Definition Protocol.hpp:149
std::uint16_t tickRateHz
Definition Protocol.hpp:150
std::uint16_t mtuPayloadBytes
Definition Protocol.hpp:151
std::uint32_t serverCaps
Definition Protocol.hpp:152
CONNECT packet payload.
Definition Protocol.hpp:138
std::array< char, 32 > playerName
Definition Protocol.hpp:140
std::uint32_t clientCaps
Definition Protocol.hpp:141
std::uint8_t nameLen
Definition Protocol.hpp:139
DISCONNECT packet payload.
Definition Protocol.hpp:159
std::uint16_t reasonCode
Definition Protocol.hpp:160
ERROR packet payload.
Definition Protocol.hpp:217
std::uint16_t msgLen
Definition Protocol.hpp:219
std::uint16_t errorCode
Definition Protocol.hpp:218
std::string description
Definition Protocol.hpp:220
GAME_START packet payload.
Definition Protocol.hpp:309
std::uint32_t lobbyId
Definition Protocol.hpp:310
Packet header according to RNP specification (Big Endian) Total size: 7 bytes (1 + 2 + 4)
Definition Protocol.hpp:128
std::uint32_t sessionId
Definition Protocol.hpp:131
std::uint8_t type
Definition Protocol.hpp:129
std::uint16_t length
Definition Protocol.hpp:130
LOBBY_CREATE_RESPONSE packet payload.
Definition Protocol.hpp:272
LOBBY_CREATE packet payload.
Definition Protocol.hpp:261
std::array< char, 32 > lobbyName
Definition Protocol.hpp:263
std::uint8_t maxPlayers
Definition Protocol.hpp:264
std::uint8_t gameMode
Definition Protocol.hpp:265
LOBBY_JOIN_RESPONSE packet payload.
Definition Protocol.hpp:290
LOBBY_JOIN packet payload.
Definition Protocol.hpp:282
std::uint32_t lobbyId
Definition Protocol.hpp:283
LOBBY_LIST_RESPONSE packet payload.
Definition Protocol.hpp:252
std::vector< LobbyInfo > lobbies
Definition Protocol.hpp:254
LOBBY_UPDATE packet payload.
Definition Protocol.hpp:301
PING/PONG packet payload.
Definition Protocol.hpp:208
std::uint32_t sendTimeMs
Definition Protocol.hpp:210
std::uint32_t nonce
Definition Protocol.hpp:209
START_GAME_REQUEST packet payload (client requests to start game)
Definition Protocol.hpp:317
WORLD_STATE packet payload.
Definition Protocol.hpp:198
std::uint16_t entityCount
Definition Protocol.hpp:200
std::uint32_t serverTick
Definition Protocol.hpp:199
std::vector< EntityState > entities
Definition Protocol.hpp:201