]> git.localhorst.tv Git - blank.git/blob - src/net/Packet.hpp
grouped entity physics state into a struct
[blank.git] / src / net / Packet.hpp
1 #ifndef BLANK_NET_PACKET_HPP_
2 #define BLANK_NET_PACKET_HPP_
3
4 #include <cstdint>
5 #include <ostream>
6 #include <string>
7 #include <SDL_net.h>
8
9
10 namespace blank {
11
12 class Entity;
13 class EntityState;
14
15 struct Packet {
16
17         static constexpr std::uint32_t TAG = 0xFB1AB1AF;
18
19         static const char *Type2String(std::uint8_t) noexcept;
20
21         struct TControl {
22                 std::uint16_t seq;
23                 std::uint16_t ack;
24                 std::uint32_t hist;
25
26                 // true if this contains an ack for given (remote) seq
27                 bool Acks(std::uint16_t) const noexcept;
28                 std::uint16_t AckBegin() const noexcept { return ack; }
29                 std::uint16_t AckEnd() const noexcept { return ack + std::uint16_t(33); }
30         };
31
32         struct Header {
33                 std::uint32_t tag;
34                 TControl ctrl;
35                 std::uint8_t type;
36                 std::uint8_t reserved1;
37                 std::uint8_t reserved2;
38                 std::uint8_t reserved3;
39         } header;
40
41         static constexpr std::size_t MAX_PAYLOAD_LEN = 500 - sizeof(Header);
42
43         std::uint8_t payload[MAX_PAYLOAD_LEN];
44
45
46         void Tag() noexcept { header.tag = TAG; }
47
48         void Type(std::uint8_t t) noexcept { header.type = t; }
49         std::uint8_t Type() const noexcept { return header.type; }
50         const char *TypeString() const noexcept { return Type2String(Type()); }
51
52
53         struct Payload {
54                 std::size_t length;
55                 std::uint8_t *data;
56
57                 std::uint16_t Seq() const noexcept {
58                         return reinterpret_cast<const Packet *>(data - sizeof(Header))->header.ctrl.seq;
59                 }
60
61                 template<class T>
62                 void Write(const T &, size_t off) noexcept;
63                 template<class T>
64                 void Read(T &, size_t off) const noexcept;
65
66                 void WriteString(const std::string &src, std::size_t off, std::size_t maxlen) noexcept;
67                 void ReadString(std::string &dst, std::size_t off, std::size_t maxlen) const noexcept;
68         };
69
70         struct Ping : public Payload {
71                 static constexpr std::uint8_t TYPE = 0;
72                 static constexpr std::size_t MAX_LEN = 0;
73         };
74
75         struct Login : public Payload {
76                 static constexpr std::uint8_t TYPE = 1;
77                 static constexpr std::size_t MAX_LEN = 32;
78
79                 void WritePlayerName(const std::string &) noexcept;
80                 void ReadPlayerName(std::string &) const noexcept;
81         };
82
83         struct Join : public Payload {
84                 static constexpr std::uint8_t TYPE = 2;
85                 static constexpr std::size_t MAX_LEN = 100;
86
87                 void WritePlayer(const Entity &) noexcept;
88                 void ReadPlayerID(std::uint32_t &) const noexcept;
89                 void ReadPlayerState(EntityState &) const noexcept;
90                 void WriteWorldName(const std::string &) noexcept;
91                 void ReadWorldName(std::string &) const noexcept;
92         };
93
94         struct Part : public Payload {
95                 static constexpr std::uint8_t TYPE = 3;
96                 static constexpr std::size_t MAX_LEN = 0;
97         };
98
99         struct PlayerUpdate : public Payload {
100                 static constexpr std::uint8_t TYPE = 4;
101                 static constexpr std::size_t MAX_LEN = 64;
102
103                 void WritePlayer(const Entity &) noexcept;
104                 void ReadPlayerState(EntityState &) const noexcept;
105         };
106
107         struct SpawnEntity : public Payload {
108                 static constexpr std::uint8_t TYPE = 5;
109                 static constexpr std::size_t MAX_LEN = 132;
110
111                 void WriteEntity(const Entity &) noexcept;
112                 void ReadEntityID(std::uint32_t &) const noexcept;
113                 void ReadSkeletonID(std::uint32_t &) const noexcept;
114                 void ReadEntity(Entity &) const noexcept;
115         };
116
117         struct DespawnEntity : public Payload {
118                 static constexpr std::uint8_t TYPE = 6;
119                 static constexpr std::size_t MAX_LEN = 4;
120
121                 void WriteEntityID(std::uint32_t) noexcept;
122                 void ReadEntityID(std::uint32_t &) const noexcept;
123         };
124
125         struct EntityUpdate : public Payload {
126                 static constexpr std::uint8_t TYPE = 7;
127                 static constexpr std::size_t MAX_LEN = 452;
128
129                 static constexpr std::uint32_t MAX_ENTITIES = 7;
130                 static constexpr std::size_t GetSize(std::uint32_t num) noexcept {
131                         return 4 + (num * 64);
132                 }
133
134                 void WriteEntityCount(std::uint32_t) noexcept;
135                 void ReadEntityCount(std::uint32_t &) const noexcept;
136
137                 void WriteEntity(const Entity &, std::uint32_t) noexcept;
138                 void ReadEntityID(std::uint32_t &, std::uint32_t) const noexcept;
139                 void ReadEntityState(EntityState &, std::uint32_t) const noexcept;
140         };
141
142
143         template<class PayloadType>
144         PayloadType As() {
145                 PayloadType result;
146                 result.length = PayloadType::MAX_LEN;
147                 result.data = &payload[0];
148                 return result;
149         }
150
151         template<class PayloadType>
152         static PayloadType As(const UDPpacket &pack) {
153                 PayloadType result;
154                 result.length = std::min(pack.len - sizeof(Header), PayloadType::MAX_LEN);
155                 result.data = pack.data + sizeof(Header);
156                 return result;
157         }
158
159         template<class PayloadType>
160         static PayloadType Make(UDPpacket &udp_pack) {
161                 Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
162                 pack.Tag();
163                 pack.Type(PayloadType::TYPE);
164
165                 udp_pack.len = sizeof(Header) + PayloadType::MAX_LEN;
166
167                 PayloadType result;
168                 result.length = PayloadType::MAX_LEN;
169                 result.data = pack.payload;
170                 return result;
171         }
172
173 };
174
175 }
176
177 #endif