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