]> git.localhorst.tv Git - blank.git/blob - src/net/Packet.hpp
transmit player input from client to server
[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                 /// WARNING: do not use these if the data doesn not
59                 ///          point into a real packet's payload
60                 const Packet &GetPacket() const noexcept {
61                         return *reinterpret_cast<const Packet *>(data - sizeof(Header));
62                 }
63                 const Header &GetHeader() const noexcept {
64                         return GetPacket().header;
65                 }
66                 std::uint16_t Seq() const noexcept {
67                         return GetHeader().ctrl.seq;
68                 }
69
70                 template<class T>
71                 void Write(const T &, size_t off) noexcept;
72                 template<class T>
73                 void Read(T &, size_t off) const noexcept;
74
75                 void WriteString(const std::string &src, std::size_t off, std::size_t maxlen) noexcept;
76                 void ReadString(std::string &dst, std::size_t off, std::size_t maxlen) const noexcept;
77         };
78
79         struct Ping : public Payload {
80                 static constexpr std::uint8_t TYPE = 0;
81                 static constexpr std::size_t MAX_LEN = 0;
82         };
83
84         struct Login : public Payload {
85                 static constexpr std::uint8_t TYPE = 1;
86                 static constexpr std::size_t MAX_LEN = 32;
87
88                 void WritePlayerName(const std::string &) noexcept;
89                 void ReadPlayerName(std::string &) const noexcept;
90         };
91
92         struct Join : public Payload {
93                 static constexpr std::uint8_t TYPE = 2;
94                 static constexpr std::size_t MAX_LEN = 100;
95
96                 void WritePlayer(const Entity &) noexcept;
97                 void ReadPlayerID(std::uint32_t &) const noexcept;
98                 void ReadPlayerState(EntityState &) const noexcept;
99                 void WriteWorldName(const std::string &) noexcept;
100                 void ReadWorldName(std::string &) const noexcept;
101         };
102
103         struct Part : public Payload {
104                 static constexpr std::uint8_t TYPE = 3;
105                 static constexpr std::size_t MAX_LEN = 0;
106         };
107
108         struct PlayerUpdate : public Payload {
109                 static constexpr std::uint8_t TYPE = 4;
110                 static constexpr std::size_t MAX_LEN = 76;
111
112                 void WritePredictedState(const EntityState &) noexcept;
113                 void ReadPredictedState(EntityState &) const noexcept;
114                 void WriteMovement(const glm::vec3 &) noexcept;
115                 void ReadMovement(glm::vec3 &) const noexcept;
116                 void WritePitch(float) noexcept;
117                 void ReadPitch(float &) const noexcept;
118                 void WriteYaw(float) noexcept;
119                 void ReadYaw(float &) const noexcept;
120                 void WriteActions(std::uint8_t) noexcept;
121                 void ReadActions(std::uint8_t &) const noexcept;
122                 void WriteSlot(std::uint8_t) noexcept;
123                 void ReadSlot(std::uint8_t &) const noexcept;
124         };
125
126         struct SpawnEntity : public Payload {
127                 static constexpr std::uint8_t TYPE = 5;
128                 static constexpr std::size_t MAX_LEN = 132;
129
130                 void WriteEntity(const Entity &) noexcept;
131                 void ReadEntityID(std::uint32_t &) const noexcept;
132                 void ReadSkeletonID(std::uint32_t &) const noexcept;
133                 void ReadEntity(Entity &) const noexcept;
134         };
135
136         struct DespawnEntity : public Payload {
137                 static constexpr std::uint8_t TYPE = 6;
138                 static constexpr std::size_t MAX_LEN = 4;
139
140                 void WriteEntityID(std::uint32_t) noexcept;
141                 void ReadEntityID(std::uint32_t &) const noexcept;
142         };
143
144         struct EntityUpdate : public Payload {
145                 static constexpr std::uint8_t TYPE = 7;
146                 static constexpr std::size_t MAX_LEN = 480;
147
148                 static constexpr std::uint32_t MAX_ENTITIES = 7;
149                 static constexpr std::size_t GetSize(std::uint32_t num) noexcept {
150                         return 4 + (num * 68);
151                 }
152
153                 void WriteEntityCount(std::uint32_t) noexcept;
154                 void ReadEntityCount(std::uint32_t &) const noexcept;
155
156                 void WriteEntity(const Entity &, std::uint32_t) noexcept;
157                 void ReadEntityID(std::uint32_t &, std::uint32_t) const noexcept;
158                 void ReadEntityState(EntityState &, std::uint32_t) const noexcept;
159         };
160
161         struct PlayerCorrection : public Payload {
162                 static constexpr std::uint8_t TYPE = 8;
163                 static constexpr std::size_t MAX_LEN = 66;
164
165                 void WritePacketSeq(std::uint16_t) noexcept;
166                 void ReadPacketSeq(std::uint16_t &) const noexcept;
167                 void WritePlayer(const Entity &) noexcept;
168                 void ReadPlayerState(EntityState &) const noexcept;
169         };
170
171         struct ChunkBegin : public Payload {
172                 static constexpr std::uint8_t TYPE = 9;
173                 static constexpr std::size_t MAX_LEN = 24;
174
175                 void WriteTransmissionId(std::uint32_t) noexcept;
176                 void ReadTransmissionId(std::uint32_t &) const noexcept;
177                 void WriteFlags(std::uint32_t) noexcept;
178                 void ReadFlags(std::uint32_t &) const noexcept;
179                 void WriteChunkCoords(const glm::ivec3 &) noexcept;
180                 void ReadChunkCoords(glm::ivec3 &) const noexcept;
181                 void WriteDataSize(std::uint32_t) noexcept;
182                 void ReadDataSize(std::uint32_t &) const noexcept;
183         };
184
185         struct ChunkData : public Payload {
186                 static constexpr std::uint8_t TYPE = 10;
187                 static constexpr std::size_t MAX_LEN = MAX_PAYLOAD_LEN;
188                 static constexpr std::size_t MAX_DATA_LEN = MAX_LEN - 12;
189
190                 void WriteTransmissionId(std::uint32_t) noexcept;
191                 void ReadTransmissionId(std::uint32_t &) const noexcept;
192                 void WriteDataOffset(std::uint32_t) noexcept;
193                 void ReadDataOffset(std::uint32_t &) const noexcept;
194                 void WriteDataSize(std::uint32_t) noexcept;
195                 void ReadDataSize(std::uint32_t &) const noexcept;
196                 void WriteData(const std::uint8_t *, std::size_t len) noexcept;
197                 void ReadData(std::uint8_t *, std::size_t maxlen) const noexcept;
198         };
199
200
201         template<class PayloadType>
202         PayloadType As() {
203                 PayloadType result;
204                 result.length = PayloadType::MAX_LEN;
205                 result.data = &payload[0];
206                 return result;
207         }
208
209         template<class PayloadType>
210         static PayloadType As(const UDPpacket &pack) {
211                 PayloadType result;
212                 result.length = std::min(pack.len - sizeof(Header), PayloadType::MAX_LEN);
213                 result.data = pack.data + sizeof(Header);
214                 return result;
215         }
216
217         template<class PayloadType>
218         static PayloadType Make(UDPpacket &udp_pack) {
219                 Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
220                 pack.Tag();
221                 pack.Type(PayloadType::TYPE);
222
223                 udp_pack.len = sizeof(Header) + PayloadType::MAX_LEN;
224
225                 PayloadType result;
226                 result.length = PayloadType::MAX_LEN;
227                 result.data = pack.payload;
228                 return result;
229         }
230
231 };
232
233 }
234
235 #endif