]> git.localhorst.tv Git - blank.git/blob - src/net/Packet.hpp
glm backwards compatibility
[blank.git] / src / net / Packet.hpp
1 #ifndef BLANK_NET_PACKET_HPP_
2 #define BLANK_NET_PACKET_HPP_
3
4 #include "../graphics/glm.hpp"
5
6 #include <cstdint>
7 #include <ostream>
8 #include <string>
9 #include <SDL_net.h>
10
11
12 namespace blank {
13
14 class Block;
15 class Entity;
16 class EntityState;
17
18 struct Packet {
19
20         static constexpr std::uint32_t TAG = 0xFB1AB1AF;
21
22         static const char *Type2String(std::uint8_t) noexcept;
23
24         struct TControl {
25                 std::uint16_t seq;
26                 std::uint16_t ack;
27                 std::uint32_t hist;
28
29                 // true if this contains an ack for given (remote) seq
30                 bool Acks(std::uint16_t) const noexcept;
31                 std::uint16_t AckBegin() const noexcept { return ack; }
32                 std::uint16_t AckEnd() const noexcept { return ack - std::uint16_t(33); }
33         };
34
35         struct Header {
36                 std::uint32_t tag;
37                 TControl ctrl;
38                 std::uint8_t type;
39                 std::uint8_t reserved1;
40                 std::uint8_t reserved2;
41                 std::uint8_t reserved3;
42         } header;
43
44         static constexpr std::size_t MAX_PAYLOAD_LEN = 500 - sizeof(Header);
45
46         std::uint8_t payload[MAX_PAYLOAD_LEN];
47
48
49         void Tag() noexcept { header.tag = TAG; }
50
51         void Type(std::uint8_t t) noexcept { header.type = t; }
52         std::uint8_t Type() const noexcept { return header.type; }
53         const char *TypeString() const noexcept { return Type2String(Type()); }
54
55
56         struct Payload {
57                 std::size_t length;
58                 std::uint8_t *data;
59
60                 /// WARNING: do not use these if the data doesn not
61                 ///          point into a real packet's payload
62                 const Packet &GetPacket() const noexcept {
63                         return *reinterpret_cast<const Packet *>(data - sizeof(Header));
64                 }
65                 const Header &GetHeader() const noexcept {
66                         return GetPacket().header;
67                 }
68                 std::uint16_t Seq() const noexcept {
69                         return GetHeader().ctrl.seq;
70                 }
71
72                 template<class T>
73                 void Write(const T &, size_t off) noexcept;
74                 template<class T>
75                 void Read(T &, size_t off) const noexcept;
76
77                 void Write(const glm::quat &, size_t off) noexcept;
78                 void Read(glm::quat &, size_t off) const noexcept;
79                 void Write(const EntityState &, size_t off) noexcept;
80                 void Read(EntityState &, size_t off) const noexcept;
81                 void Write(const EntityState &, const glm::ivec3 &, size_t off) noexcept;
82                 void Read(EntityState &, const glm::ivec3 &, size_t off) const noexcept;
83
84                 void WriteString(const std::string &src, std::size_t off, std::size_t maxlen) noexcept;
85                 void ReadString(std::string &dst, std::size_t off, std::size_t maxlen) const noexcept;
86
87                 void WritePackB(const glm::ivec3 &, size_t off) noexcept;
88                 void ReadPackB(glm::ivec3 &, size_t off) const noexcept;
89
90                 void WritePackN(float, size_t off) noexcept;
91                 void ReadPackN(float &, size_t off) const noexcept;
92                 void WritePackN(const glm::vec3 &, size_t off) noexcept;
93                 void ReadPackN(glm::vec3 &, size_t off) const noexcept;
94
95                 void WritePackU(float, size_t off) noexcept;
96                 void ReadPackU(float &, size_t off) const noexcept;
97                 void WritePackU(const glm::vec3 &, size_t off) noexcept;
98                 void ReadPackU(glm::vec3 &, size_t off) const noexcept;
99         };
100
101         struct Ping : public Payload {
102                 static constexpr std::uint8_t TYPE = 0;
103                 static constexpr std::size_t MAX_LEN = 0;
104         };
105
106         struct Login : public Payload {
107                 static constexpr std::uint8_t TYPE = 1;
108                 static constexpr std::size_t MAX_LEN = 32;
109
110                 void WritePlayerName(const std::string &) noexcept;
111                 void ReadPlayerName(std::string &) const noexcept;
112         };
113
114         struct Join : public Payload {
115                 static constexpr std::uint8_t TYPE = 2;
116                 static constexpr std::size_t MAX_LEN = 78;
117
118                 void WritePlayer(const Entity &) noexcept;
119                 void ReadPlayerID(std::uint32_t &) const noexcept;
120                 void ReadPlayerState(EntityState &) const noexcept;
121                 void WriteWorldName(const std::string &) noexcept;
122                 void ReadWorldName(std::string &) const noexcept;
123         };
124
125         struct Part : public Payload {
126                 static constexpr std::uint8_t TYPE = 3;
127                 static constexpr std::size_t MAX_LEN = 0;
128         };
129
130         struct PlayerUpdate : public Payload {
131                 static constexpr std::uint8_t TYPE = 4;
132                 static constexpr std::size_t MAX_LEN = 50;
133
134                 void WritePredictedState(const EntityState &) noexcept;
135                 void ReadPredictedState(EntityState &) const noexcept;
136                 void WriteMovement(const glm::vec3 &) noexcept;
137                 void ReadMovement(glm::vec3 &) const noexcept;
138                 void WriteActions(std::uint8_t) noexcept;
139                 void ReadActions(std::uint8_t &) const noexcept;
140                 void WriteSlot(std::uint8_t) noexcept;
141                 void ReadSlot(std::uint8_t &) const noexcept;
142         };
143
144         struct SpawnEntity : public Payload {
145                 static constexpr std::uint8_t TYPE = 5;
146                 static constexpr std::size_t MAX_LEN = 110;
147
148                 void WriteEntity(const Entity &) noexcept;
149                 void ReadEntityID(std::uint32_t &) const noexcept;
150                 void ReadModelID(std::uint32_t &) const noexcept;
151                 void ReadEntity(Entity &) const noexcept;
152         };
153
154         struct DespawnEntity : public Payload {
155                 static constexpr std::uint8_t TYPE = 6;
156                 static constexpr std::size_t MAX_LEN = 4;
157
158                 void WriteEntityID(std::uint32_t) noexcept;
159                 void ReadEntityID(std::uint32_t &) const noexcept;
160         };
161
162         struct EntityUpdate : public Payload {
163                 static constexpr std::uint8_t TYPE = 7;
164                 static constexpr std::size_t MAX_LEN = 460;
165
166                 static constexpr std::uint32_t MAX_ENTITIES = 12;
167                 static constexpr std::size_t GetSize(std::uint32_t num) noexcept {
168                         return 16 + (num * 37);
169                 }
170
171                 void WriteEntityCount(std::uint32_t) noexcept;
172                 void ReadEntityCount(std::uint32_t &) const noexcept;
173                 void WriteChunkBase(const glm::ivec3 &) noexcept;
174                 void ReadChunkBase(glm::ivec3 &) const noexcept;
175
176                 void WriteEntity(const Entity &, const glm::ivec3 &, std::uint32_t) noexcept;
177                 void ReadEntityID(std::uint32_t &, std::uint32_t) const noexcept;
178                 void ReadEntityState(EntityState &, const glm::ivec3 &, std::uint32_t) const noexcept;
179         };
180
181         struct PlayerCorrection : public Payload {
182                 static constexpr std::uint8_t TYPE = 8;
183                 static constexpr std::size_t MAX_LEN = 44;
184
185                 void WritePacketSeq(std::uint16_t) noexcept;
186                 void ReadPacketSeq(std::uint16_t &) const noexcept;
187                 void WritePlayer(const Entity &) noexcept;
188                 void ReadPlayerState(EntityState &) const noexcept;
189         };
190
191         struct ChunkBegin : public Payload {
192                 static constexpr std::uint8_t TYPE = 9;
193                 static constexpr std::size_t MAX_LEN = 24;
194
195                 void WriteTransmissionId(std::uint32_t) noexcept;
196                 void ReadTransmissionId(std::uint32_t &) const noexcept;
197                 void WriteFlags(std::uint32_t) noexcept;
198                 void ReadFlags(std::uint32_t &) const noexcept;
199                 void WriteChunkCoords(const glm::ivec3 &) noexcept;
200                 void ReadChunkCoords(glm::ivec3 &) const noexcept;
201                 void WriteDataSize(std::uint32_t) noexcept;
202                 void ReadDataSize(std::uint32_t &) const noexcept;
203         };
204
205         struct ChunkData : public Payload {
206                 static constexpr std::uint8_t TYPE = 10;
207                 static constexpr std::size_t MAX_LEN = MAX_PAYLOAD_LEN;
208                 static constexpr std::size_t MAX_DATA_LEN = MAX_LEN - 12;
209
210                 static constexpr std::size_t GetSize(std::size_t data_len) noexcept {
211                         return data_len + 12;
212                 }
213
214                 void WriteTransmissionId(std::uint32_t) noexcept;
215                 void ReadTransmissionId(std::uint32_t &) const noexcept;
216                 void WriteDataOffset(std::uint32_t) noexcept;
217                 void ReadDataOffset(std::uint32_t &) const noexcept;
218                 void WriteDataSize(std::uint32_t) noexcept;
219                 void ReadDataSize(std::uint32_t &) const noexcept;
220                 void WriteData(const std::uint8_t *, std::size_t len) noexcept;
221                 void ReadData(std::uint8_t *, std::size_t maxlen) const noexcept;
222         };
223
224         struct BlockUpdate : public Payload {
225                 static constexpr std::uint8_t TYPE = 11;
226                 static constexpr std::size_t MAX_LEN = 484;
227
228                 static constexpr std::uint32_t MAX_BLOCKS = 78;
229                 static constexpr std::size_t GetSize(std::uint32_t num) noexcept {
230                         return 16 + (num * 6);
231                 }
232
233                 void WriteChunkCoords(const glm::ivec3 &) noexcept;
234                 void ReadChunkCoords(glm::ivec3 &) const noexcept;
235                 void WriteBlockCount(std::uint32_t) noexcept;
236                 void ReadBlockCount(std::uint32_t &) const noexcept;
237
238                 void WriteIndex(std::uint16_t, std::uint32_t) noexcept;
239                 void ReadIndex(std::uint16_t &, std::uint32_t) const noexcept;
240                 void WriteBlock(const Block &, std::uint32_t) noexcept;
241                 void ReadBlock(Block &, std::uint32_t) const noexcept;
242         };
243
244         struct Message : public Payload {
245                 static constexpr std::uint8_t TYPE = 12;
246                 static constexpr std::size_t MAX_LEN = 455;
247
248                 static constexpr std::size_t MAX_MESSAGE_LEN = 450;
249                 static std::size_t GetSize(const std::string &msg) noexcept {
250                         return 5 + std::min(msg.size() + 1, MAX_MESSAGE_LEN);
251                 }
252
253                 void WriteType(std::uint8_t) noexcept;
254                 void ReadType(std::uint8_t &) const noexcept;
255                 void WriteReferral(std::uint32_t) noexcept;
256                 void ReadReferral(std::uint32_t &) const noexcept;
257                 void WriteMessage(const std::string &) noexcept;
258                 void ReadMessage(std::string &) const noexcept;
259         };
260
261
262         template<class PayloadType>
263         PayloadType As() {
264                 PayloadType result;
265                 result.length = PayloadType::MAX_LEN;
266                 result.data = &payload[0];
267                 return result;
268         }
269
270         template<class PayloadType>
271         static PayloadType As(const UDPpacket &pack) {
272                 PayloadType result;
273                 result.length = std::min(pack.len - sizeof(Header), PayloadType::MAX_LEN);
274                 result.data = pack.data + sizeof(Header);
275                 return result;
276         }
277
278         template<class PayloadType>
279         static PayloadType Make(UDPpacket &udp_pack) {
280                 Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
281                 pack.Tag();
282                 pack.Type(PayloadType::TYPE);
283
284                 udp_pack.len = sizeof(Header) + PayloadType::MAX_LEN;
285
286                 PayloadType result;
287                 result.length = PayloadType::MAX_LEN;
288                 result.data = pack.payload;
289                 return result;
290         }
291
292 };
293
294 }
295
296 #endif