X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fnet%2FPacket.hpp;h=4ff45df53b6e5a136310b57991087b3249d35549;hb=b5a83cd3df5083ed0cccfe4876143e788b3836f9;hp=0d99fee2992c74c61a1979dfe251813c69e607ca;hpb=da5073a7fdb1ca066e778a02db33d5d15073aea0;p=blank.git diff --git a/src/net/Packet.hpp b/src/net/Packet.hpp index 0d99fee..4ff45df 100644 --- a/src/net/Packet.hpp +++ b/src/net/Packet.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace blank { @@ -14,44 +15,122 @@ struct Packet { static constexpr std::uint32_t TAG = 0xFB1AB1AF; - enum Type { - PING = 0, - LOGIN = 1, - JOIN = 2, - PART = 3, - }; - - static const char *Type2String(Type) noexcept; + static const char *Type2String(std::uint8_t) noexcept; struct TControl { std::uint16_t seq; std::uint16_t ack; std::uint32_t hist; + + // true if this contains an ack for given (remote) seq + bool Acks(std::uint16_t) const noexcept; + std::uint16_t AckBegin() const noexcept { return ack; } + std::uint16_t AckEnd() const noexcept { return ack + std::uint16_t(33); } }; struct Header { std::uint32_t tag; TControl ctrl; std::uint8_t type; + std::uint8_t reserved1; + std::uint8_t reserved2; + std::uint8_t reserved3; } header; - std::uint8_t payload[500 - sizeof(Header)]; + static constexpr std::size_t MAX_PAYLOAD_LEN = 500 - sizeof(Header); + std::uint8_t payload[MAX_PAYLOAD_LEN]; - Type GetType() const noexcept { return Type(header.type); } - void Tag() noexcept; + void Tag() noexcept { header.tag = TAG; } - std::size_t MakePing() noexcept; - std::size_t MakeLogin(const std::string &name) noexcept; - std::size_t MakeJoin(const Entity &player, const std::string &world_name) noexcept; - std::size_t MakePart() noexcept; + 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()); } -}; -inline std::ostream &operator <<(std::ostream &out, Packet::Type t) { - return out << Packet::Type2String(t); -} + struct Payload { + std::size_t length; + std::uint8_t *data; + + template + void Write(const T &, size_t off) noexcept; + template + 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 + PayloadType As() { + PayloadType result; + result.length = PayloadType::MAX_LEN; + result.data = &payload[0]; + return result; + } + + template + 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; + } + + template + static PayloadType Make(UDPpacket &udp_pack) { + Packet &pack = *reinterpret_cast(udp_pack.data); + pack.Tag(); + pack.Type(PayloadType::TYPE); + + udp_pack.len = sizeof(Header) + PayloadType::MAX_LEN; + + PayloadType result; + result.length = PayloadType::MAX_LEN; + result.data = pack.payload; + return result; + } + +}; }