]> git.localhorst.tv Git - blank.git/blob - src/net/Packet.hpp
transmit chunks from server to client
[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 #include <glm/glm.hpp>
9
10
11 namespace blank {
12
13 class Entity;
14 class EntityState;
15
16 struct Packet {
17
18         static constexpr std::uint32_t TAG = 0xFB1AB1AF;
19
20         static const char *Type2String(std::uint8_t) noexcept;
21
22         struct TControl {
23                 std::uint16_t seq;
24                 std::uint16_t ack;
25                 std::uint32_t hist;
26
27                 // true if this contains an ack for given (remote) seq
28                 bool Acks(std::uint16_t) const noexcept;
29                 std::uint16_t AckBegin() const noexcept { return ack; }
30                 std::uint16_t AckEnd() const noexcept { return ack - std::uint16_t(33); }
31         };
32
33         struct Header {
34                 std::uint32_t tag;
35                 TControl ctrl;
36                 std::uint8_t type;
37                 std::uint8_t reserved1;
38                 std::uint8_t reserved2;
39                 std::uint8_t reserved3;
40         } header;
41
42         static constexpr std::size_t MAX_PAYLOAD_LEN = 500 - sizeof(Header);
43
44         std::uint8_t payload[MAX_PAYLOAD_LEN];
45
46
47         void Tag() noexcept { header.tag = TAG; }
48
49         void Type(std::uint8_t t) noexcept { header.type = t; }
50         std::uint8_t Type() const noexcept { return header.type; }
51         const char *TypeString() const noexcept { return Type2String(Type()); }
52
53
54         struct Payload {
55                 std::size_t length;
56                 std::uint8_t *data;
57
58                 std::uint16_t Seq() const noexcept {
59                         return reinterpret_cast<const Packet *>(data - sizeof(Header))->header.ctrl.seq;
60                 }
61
62                 template<class T>
63                 void Write(const T &, size_t off) noexcept;
64                 template<class T>
65                 void Read(T &, size_t off) const noexcept;
66
67                 void WriteString(const std::string &src, std::size_t off, std::size_t maxlen) noexcept;
68                 void ReadString(std::string &dst, std::size_t off, std::size_t maxlen) const noexcept;
69         };
70
71         struct Ping : public Payload {
72                 static constexpr std::uint8_t TYPE = 0;
73                 static constexpr std::size_t MAX_LEN = 0;
74         };
75
76         struct Login : public Payload {
77                 static constexpr std::uint8_t TYPE = 1;
78                 static constexpr std::size_t MAX_LEN = 32;
79
80                 void WritePlayerName(const std::string &) noexcept;
81                 void ReadPlayerName(std::string &) const noexcept;
82         };
83
84         struct Join : public Payload {
85                 static constexpr std::uint8_t TYPE = 2;
86                 static constexpr std::size_t MAX_LEN = 100;
87
88                 void WritePlayer(const Entity &) noexcept;
89                 void ReadPlayerID(std::uint32_t &) const noexcept;
90                 void ReadPlayerState(EntityState &) const noexcept;
91                 void WriteWorldName(const std::string &) noexcept;
92                 void ReadWorldName(std::string &) const noexcept;
93         };
94
95         struct Part : public Payload {
96                 static constexpr std::uint8_t TYPE = 3;
97                 static constexpr std::size_t MAX_LEN = 0;
98         };
99
100         struct PlayerUpdate : public Payload {
101                 static constexpr std::uint8_t TYPE = 4;
102                 static constexpr std::size_t MAX_LEN = 64;
103
104                 void WritePlayer(const Entity &) noexcept;
105                 void ReadPlayerState(EntityState &) const noexcept;
106         };
107
108         struct SpawnEntity : public Payload {
109                 static constexpr std::uint8_t TYPE = 5;
110                 static constexpr std::size_t MAX_LEN = 132;
111
112                 void WriteEntity(const Entity &) noexcept;
113                 void ReadEntityID(std::uint32_t &) const noexcept;
114                 void ReadSkeletonID(std::uint32_t &) const noexcept;
115                 void ReadEntity(Entity &) const noexcept;
116         };
117
118         struct DespawnEntity : public Payload {
119                 static constexpr std::uint8_t TYPE = 6;
120                 static constexpr std::size_t MAX_LEN = 4;
121
122                 void WriteEntityID(std::uint32_t) noexcept;
123                 void ReadEntityID(std::uint32_t &) const noexcept;
124         };
125
126         struct EntityUpdate : public Payload {
127                 static constexpr std::uint8_t TYPE = 7;
128                 static constexpr std::size_t MAX_LEN = 452;
129
130                 static constexpr std::uint32_t MAX_ENTITIES = 7;
131                 static constexpr std::size_t GetSize(std::uint32_t num) noexcept {
132                         return 4 + (num * 64);
133                 }
134
135                 void WriteEntityCount(std::uint32_t) noexcept;
136                 void ReadEntityCount(std::uint32_t &) const noexcept;
137
138                 void WriteEntity(const Entity &, std::uint32_t) noexcept;
139                 void ReadEntityID(std::uint32_t &, std::uint32_t) const noexcept;
140                 void ReadEntityState(EntityState &, std::uint32_t) const noexcept;
141         };
142
143         struct PlayerCorrection : public Payload {
144                 static constexpr std::uint8_t TYPE = 8;
145                 static constexpr std::size_t MAX_LEN = 66;
146
147                 void WritePacketSeq(std::uint16_t) noexcept;
148                 void ReadPacketSeq(std::uint16_t &) const noexcept;
149                 void WritePlayer(const Entity &) noexcept;
150                 void ReadPlayerState(EntityState &) const noexcept;
151         };
152
153         struct ChunkBegin : public Payload {
154                 static constexpr std::uint8_t TYPE = 9;
155                 static constexpr std::size_t MAX_LEN = 24;
156
157                 void WriteTransmissionId(std::uint32_t) noexcept;
158                 void ReadTransmissionId(std::uint32_t &) const noexcept;
159                 void WriteFlags(std::uint32_t) noexcept;
160                 void ReadFlags(std::uint32_t &) const noexcept;
161                 void WriteChunkCoords(const glm::ivec3 &) noexcept;
162                 void ReadChunkCoords(glm::ivec3 &) const noexcept;
163                 void WriteDataSize(std::uint32_t) noexcept;
164                 void ReadDataSize(std::uint32_t &) const noexcept;
165         };
166
167         struct ChunkData : public Payload {
168                 static constexpr std::uint8_t TYPE = 10;
169                 static constexpr std::size_t MAX_LEN = MAX_PAYLOAD_LEN;
170                 static constexpr std::size_t MAX_DATA_LEN = MAX_LEN - 12;
171
172                 void WriteTransmissionId(std::uint32_t) noexcept;
173                 void ReadTransmissionId(std::uint32_t &) const noexcept;
174                 void WriteDataOffset(std::uint32_t) noexcept;
175                 void ReadDataOffset(std::uint32_t &) const noexcept;
176                 void WriteDataSize(std::uint32_t) noexcept;
177                 void ReadDataSize(std::uint32_t &) const noexcept;
178                 void WriteData(const std::uint8_t *, std::size_t len) noexcept;
179                 void ReadData(std::uint8_t *, std::size_t maxlen) const noexcept;
180         };
181
182
183         template<class PayloadType>
184         PayloadType As() {
185                 PayloadType result;
186                 result.length = PayloadType::MAX_LEN;
187                 result.data = &payload[0];
188                 return result;
189         }
190
191         template<class PayloadType>
192         static PayloadType As(const UDPpacket &pack) {
193                 PayloadType result;
194                 result.length = std::min(pack.len - sizeof(Header), PayloadType::MAX_LEN);
195                 result.data = pack.data + sizeof(Header);
196                 return result;
197         }
198
199         template<class PayloadType>
200         static PayloadType Make(UDPpacket &udp_pack) {
201                 Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
202                 pack.Tag();
203                 pack.Type(PayloadType::TYPE);
204
205                 udp_pack.len = sizeof(Header) + PayloadType::MAX_LEN;
206
207                 PayloadType result;
208                 result.length = PayloadType::MAX_LEN;
209                 result.data = pack.payload;
210                 return result;
211         }
212
213 };
214
215 }
216
217 #endif