+ static constexpr std::size_t MAX_PAYLOAD_LEN = 500 - sizeof(Header);
+
+ std::uint8_t payload[MAX_PAYLOAD_LEN];
+
+
+ void Tag() noexcept { header.tag = TAG; }
+
+ void Type(std::uint8_t t) noexcept { header.type = t; }
+ std::uint8_t Type() const noexcept { return header.type; }
+ const char *TypeString() const noexcept { return Type2String(Type()); }
+
+
+ struct Payload {
+ std::size_t length;
+ std::uint8_t *data;
+
+ template<class T>
+ void Write(const T &, size_t off) noexcept;
+ template<class T>
+ void Read(T &, size_t off) const noexcept;
+
+ void WriteString(const std::string &src, std::size_t off, std::size_t maxlen) noexcept;
+ void ReadString(std::string &dst, std::size_t off, std::size_t maxlen) const noexcept;
+ };
+
+ struct Ping : public Payload {
+ static constexpr std::uint8_t TYPE = 0;
+ static constexpr std::size_t MAX_LEN = 0;
+ };
+
+ struct Login : public Payload {
+ static constexpr std::uint8_t TYPE = 1;
+ static constexpr std::size_t MAX_LEN = 32;
+
+ void WritePlayerName(const std::string &) noexcept;
+ void ReadPlayerName(std::string &) const noexcept;
+ };
+
+ struct Join : public Payload {
+ static constexpr std::uint8_t TYPE = 2;
+ static constexpr std::size_t MAX_LEN = 100;
+
+ void WritePlayer(const Entity &) noexcept;
+ void ReadPlayerID(std::uint32_t &) const noexcept;
+ void ReadPlayer(Entity &) const noexcept;
+ void WriteWorldName(const std::string &) noexcept;
+ void ReadWorldName(std::string &) const noexcept;
+ };
+
+ struct Part : public Payload {
+ static constexpr std::uint8_t TYPE = 3;
+ static constexpr std::size_t MAX_LEN = 0;
+ };
+
+ struct PlayerUpdate : public Payload {
+ static constexpr std::uint8_t TYPE = 4;
+ static constexpr std::size_t MAX_LEN = 64;
+
+ void WritePlayer(const Entity &) noexcept;
+ void ReadPlayer(Entity &) const noexcept;
+ };
+
+
+ template<class PayloadType>
+ PayloadType As() {
+ PayloadType result;
+ result.length = PayloadType::MAX_LEN;
+ result.data = &payload[0];
+ return result;
+ }
+
+ template<class PayloadType>
+ static PayloadType As(const UDPpacket &pack) {
+ PayloadType result;
+ result.length = std::min(pack.len - sizeof(Header), PayloadType::MAX_LEN);
+ result.data = pack.data + sizeof(Header);
+ return result;
+ }