]> git.localhorst.tv Git - blank.git/blob - src/net/net.cpp
more packet introspection from payload
[blank.git] / src / net / net.cpp
1 #include "Client.hpp"
2 #include "ClientConnection.hpp"
3 #include "Connection.hpp"
4 #include "ConnectionHandler.hpp"
5 #include "io.hpp"
6 #include "Packet.hpp"
7 #include "Server.hpp"
8
9 #include "../app/init.hpp"
10 #include "../model/CompositeModel.hpp"
11 #include "../world/ChunkIndex.hpp"
12 #include "../world/Entity.hpp"
13 #include "../world/EntityState.hpp"
14 #include "../world/World.hpp"
15
16 #include <cstring>
17 #include <iostream>
18 #include <glm/gtx/io.hpp>
19
20 using namespace std;
21
22
23 namespace blank {
24
25 constexpr size_t Packet::Ping::MAX_LEN;
26 constexpr size_t Packet::Login::MAX_LEN;
27 constexpr size_t Packet::Join::MAX_LEN;
28 constexpr size_t Packet::Part::MAX_LEN;
29 constexpr size_t Packet::PlayerUpdate::MAX_LEN;
30 constexpr size_t Packet::SpawnEntity::MAX_LEN;
31 constexpr size_t Packet::DespawnEntity::MAX_LEN;
32 constexpr size_t Packet::EntityUpdate::MAX_LEN;
33 constexpr size_t Packet::PlayerCorrection::MAX_LEN;
34 constexpr size_t Packet::ChunkBegin::MAX_LEN;
35 constexpr size_t Packet::ChunkData::MAX_LEN;
36
37 namespace {
38
39 UDPsocket client_bind(Uint16 port) {
40         UDPsocket sock = SDLNet_UDP_Open(port);
41         if (!sock) {
42                 throw NetError("SDLNet_UDP_Open");
43         }
44         return sock;
45 }
46
47 IPaddress client_resolve(const char *host, Uint16 port) {
48         IPaddress addr;
49         if (SDLNet_ResolveHost(&addr, host, port) != 0) {
50                 throw NetError("SDLNet_ResolveHost");
51         }
52         return addr;
53 }
54
55 }
56
57 Client::Client(const Config &conf)
58 : conn(client_resolve(conf.host.c_str(), conf.port))
59 , client_sock(client_bind(0))
60 , client_pack{ -1, nullptr, 0 } {
61         client_pack.data = new Uint8[sizeof(Packet)];
62         client_pack.maxlen = sizeof(Packet);
63         // establish connection
64         SendPing();
65 }
66
67 Client::~Client() {
68         delete[] client_pack.data;
69         SDLNet_UDP_Close(client_sock);
70 }
71
72
73 void Client::Handle() {
74         int result = SDLNet_UDP_Recv(client_sock, &client_pack);
75         while (result > 0) {
76                 HandlePacket(client_pack);
77                 result = SDLNet_UDP_Recv(client_sock, &client_pack);
78         }
79         if (result == -1) {
80                 // a boo boo happened
81                 throw NetError("SDLNet_UDP_Recv");
82         }
83 }
84
85 void Client::HandlePacket(const UDPpacket &udp_pack) {
86         if (!conn.Matches(udp_pack.address)) {
87                 // packet came from somewhere else, drop
88                 return;
89         }
90         const Packet &pack = *reinterpret_cast<const Packet *>(udp_pack.data);
91         if (pack.header.tag != Packet::TAG) {
92                 // mistagged packet, drop
93                 return;
94         }
95
96         conn.Received(udp_pack);
97 }
98
99 void Client::Update(int dt) {
100         conn.Update(dt);
101         if (conn.ShouldPing()) {
102                 SendPing();
103         }
104 }
105
106 uint16_t Client::SendPing() {
107         return conn.SendPing(client_pack, client_sock);
108 }
109
110 uint16_t Client::SendLogin(const string &name) {
111         auto pack = Packet::Make<Packet::Login>(client_pack);
112         pack.WritePlayerName(name);
113         return conn.Send(client_pack, client_sock);
114 }
115
116 uint16_t Client::SendPlayerUpdate(const Entity &player) {
117         auto pack = Packet::Make<Packet::PlayerUpdate>(client_pack);
118         pack.WritePlayer(player);
119         return conn.Send(client_pack, client_sock);
120 }
121
122 uint16_t Client::SendPart() {
123         Packet::Make<Packet::Part>(client_pack);
124         return conn.Send(client_pack, client_sock);
125 }
126
127
128 ClientConnection::ClientConnection(Server &server, const IPaddress &addr)
129 : server(server)
130 , conn(addr)
131 , player(nullptr, nullptr)
132 , spawns()
133 , confirm_wait(0)
134 , player_update_state()
135 , player_update_pack(0)
136 , player_update_timer(1500)
137 , transmitter(*this)
138 , chunk_queue()
139 , old_base() {
140         conn.SetHandler(this);
141 }
142
143 ClientConnection::~ClientConnection() {
144         DetachPlayer();
145 }
146
147 void ClientConnection::Update(int dt) {
148         conn.Update(dt);
149         if (Disconnected()) {
150                 return;
151         }
152         if (HasPlayer()) {
153                 // sync entities
154                 auto global_iter = server.GetWorld().Entities().begin();
155                 auto global_end = server.GetWorld().Entities().end();
156                 auto local_iter = spawns.begin();
157                 auto local_end = spawns.end();
158
159                 while (global_iter != global_end && local_iter != local_end) {
160                         if (global_iter->ID() == local_iter->entity->ID()) {
161                                 // they're the same
162                                 if (CanDespawn(*global_iter)) {
163                                         SendDespawn(*local_iter);
164                                 } else {
165                                         // update
166                                         SendUpdate(*local_iter);
167                                 }
168                                 ++global_iter;
169                                 ++local_iter;
170                         } else if (global_iter->ID() < local_iter->entity->ID()) {
171                                 // global entity was inserted
172                                 if (CanSpawn(*global_iter)) {
173                                         auto spawned = spawns.emplace(local_iter, *global_iter);
174                                         SendSpawn(*spawned);
175                                 }
176                                 ++global_iter;
177                         } else {
178                                 // global entity was removed
179                                 SendDespawn(*local_iter);
180                                 ++local_iter;
181                         }
182                 }
183
184                 // leftover spawns
185                 while (global_iter != global_end) {
186                         if (CanSpawn(*global_iter)) {
187                                 spawns.emplace_back(*global_iter);
188                                 SendSpawn(spawns.back());
189                         }
190                         ++global_iter;
191                 }
192
193                 // leftover despawns
194                 while (local_iter != local_end) {
195                         SendDespawn(*local_iter);
196                         ++local_iter;
197                 }
198
199                 CheckPlayerFix();
200                 CheckChunkQueue();
201         }
202         if (conn.ShouldPing()) {
203                 conn.SendPing(server.GetPacket(), server.GetSocket());
204         }
205 }
206
207 ClientConnection::SpawnStatus::SpawnStatus(Entity &e)
208 : entity(&e)
209 , spawn_pack(-1)
210 , despawn_pack(-1) {
211         entity->Ref();
212 }
213
214 ClientConnection::SpawnStatus::~SpawnStatus() {
215         entity->UnRef();
216 }
217
218 bool ClientConnection::CanSpawn(const Entity &e) const noexcept {
219         return
220                 &e != player.entity &&
221                 !e.Dead() &&
222                 manhattan_radius(e.ChunkCoords() - PlayerEntity().ChunkCoords()) < 7;
223 }
224
225 bool ClientConnection::CanDespawn(const Entity &e) const noexcept {
226         return
227                 e.Dead() ||
228                 manhattan_radius(e.ChunkCoords() - PlayerEntity().ChunkCoords()) > 7;
229 }
230
231 uint16_t ClientConnection::Send() {
232         return conn.Send(server.GetPacket(), server.GetSocket());
233 }
234
235 uint16_t ClientConnection::Send(size_t len) {
236         server.GetPacket().len = len;
237         return Send();
238 }
239
240 void ClientConnection::SendSpawn(SpawnStatus &status) {
241         // don't double spawn
242         if (status.spawn_pack != -1) return;
243
244         auto pack = Prepare<Packet::SpawnEntity>();
245         pack.WriteEntity(*status.entity);
246         status.spawn_pack = Send();
247         ++confirm_wait;
248 }
249
250 void ClientConnection::SendDespawn(SpawnStatus &status) {
251         // don't double despawn
252         if (status.despawn_pack != -1) return;
253
254         auto pack = Prepare<Packet::DespawnEntity>();
255         pack.WriteEntityID(status.entity->ID());
256         status.despawn_pack = Send();
257         ++confirm_wait;
258 }
259
260 void ClientConnection::SendUpdate(SpawnStatus &status) {
261         // don't send updates while spawn not ack'd or despawn sent
262         if (status.spawn_pack != -1 || status.despawn_pack != -1) return;
263
264         // TODO: pack entity updates
265         auto pack = Prepare<Packet::EntityUpdate>();
266         pack.WriteEntityCount(1);
267         pack.WriteEntity(*status.entity, 0);
268         Send(Packet::EntityUpdate::GetSize(1));
269 }
270
271 void ClientConnection::CheckPlayerFix() {
272         // player_update_state's position holds the client's most recent prediction
273         glm::vec3 diff = player_update_state.Diff(PlayerEntity().GetState());
274         float dist_squared = dot(diff, diff);
275
276         // if client's prediction is off by more than 1cm, send
277         // our (authoritative) state back so it can fix it
278         constexpr float fix_thresh = 0.0001f;
279
280         if (dist_squared > fix_thresh) {
281                 auto pack = Prepare<Packet::PlayerCorrection>();
282                 pack.WritePacketSeq(player_update_pack);
283                 pack.WritePlayer(PlayerEntity());
284                 Send();
285         }
286 }
287
288 void ClientConnection::CheckChunkQueue() {
289         if (PlayerChunks().Base() != old_base) {
290                 Chunk::Pos begin = PlayerChunks().CoordsBegin();
291                 Chunk::Pos end = PlayerChunks().CoordsEnd();
292                 for (Chunk::Pos pos = begin; pos.z < end.z; ++pos.z) {
293                         for (pos.y = begin.y; pos.y < end.y; ++pos.y) {
294                                 for (pos.x = begin.x; pos.x < end.x; ++pos.x) {
295                                         if (manhattan_radius(pos - old_base) > PlayerChunks().Extent()) {
296                                                 chunk_queue.push_back(pos);
297                                         }
298                                 }
299                         }
300                 }
301                 old_base = PlayerChunks().Base();
302         }
303         if (transmitter.Transmitting()) {
304                 transmitter.Transmit();
305                 return;
306         }
307         if (transmitter.Idle()) {
308                 int count = 0;
309                 constexpr int max = 64;
310                 while (count < max && !chunk_queue.empty()) {
311                         Chunk::Pos pos = chunk_queue.front();
312                         chunk_queue.pop_front();
313                         if (PlayerChunks().InRange(pos)) {
314                                 Chunk *chunk = PlayerChunks().Get(pos);
315                                 if (chunk) {
316                                         transmitter.Send(*chunk);
317                                         return;
318                                 } else {
319                                         chunk_queue.push_back(pos);
320                                 }
321                                 ++count;
322                         }
323                 }
324         }
325 }
326
327 void ClientConnection::AttachPlayer(const Player &new_player) {
328         DetachPlayer();
329         player = new_player;
330         player.entity->Ref();
331
332         old_base = player.chunks->Base();
333         Chunk::Pos begin = player.chunks->CoordsBegin();
334         Chunk::Pos end = player.chunks->CoordsEnd();
335         for (Chunk::Pos pos = begin; pos.z < end.z; ++pos.z) {
336                 for (pos.y = begin.y; pos.y < end.y; ++pos.y) {
337                         for (pos.x = begin.x; pos.x < end.x; ++pos.x) {
338                                 chunk_queue.push_back(pos);
339                         }
340                 }
341         }
342
343         cout << "player \"" << player.entity->Name() << "\" joined" << endl;
344 }
345
346 void ClientConnection::DetachPlayer() {
347         if (!HasPlayer()) return;
348         cout << "player \"" << player.entity->Name() << "\" left" << endl;
349         player.entity->Kill();
350         player.entity->UnRef();
351         player.entity = nullptr;
352         player.chunks = nullptr;
353         transmitter.Abort();
354         chunk_queue.clear();
355 }
356
357 void ClientConnection::OnPacketReceived(uint16_t seq) {
358         if (transmitter.Waiting()) {
359                 transmitter.Ack(seq);
360         }
361         if (!confirm_wait) return;
362         for (auto iter = spawns.begin(), end = spawns.end(); iter != end; ++iter) {
363                 if (seq == iter->spawn_pack) {
364                         iter->spawn_pack = -1;
365                         --confirm_wait;
366                         return;
367                 }
368                 if (seq == iter->despawn_pack) {
369                         spawns.erase(iter);
370                         --confirm_wait;
371                         return;
372                 }
373         }
374 }
375
376 void ClientConnection::OnPacketLost(uint16_t seq) {
377         if (transmitter.Waiting()) {
378                 transmitter.Nack(seq);
379         }
380         if (!confirm_wait) return;
381         for (SpawnStatus &status : spawns) {
382                 if (seq == status.spawn_pack) {
383                         status.spawn_pack = -1;
384                         --confirm_wait;
385                         SendSpawn(status);
386                         return;
387                 }
388                 if (seq == status.despawn_pack) {
389                         status.despawn_pack = -1;
390                         --confirm_wait;
391                         SendDespawn(status);
392                         return;
393                 }
394         }
395 }
396
397 void ClientConnection::On(const Packet::Login &pack) {
398         string name;
399         pack.ReadPlayerName(name);
400
401         Player new_player = server.GetWorld().AddPlayer(name);
402
403         if (new_player.entity) {
404                 // success!
405                 AttachPlayer(new_player);
406                 cout << "accepted login from player \"" << name << '"' << endl;
407                 auto response = Prepare<Packet::Join>();
408                 response.WritePlayer(*new_player.entity);
409                 response.WriteWorldName(server.GetWorld().Name());
410                 Send();
411                 // set up update tracking
412                 player_update_state = new_player.entity->GetState();
413                 player_update_pack = pack.Seq();
414                 player_update_timer.Reset();
415                 player_update_timer.Start();
416         } else {
417                 // aw no :(
418                 cout << "rejected login from player \"" << name << '"' << endl;
419                 Prepare<Packet::Part>();
420                 Send();
421                 conn.Close();
422         }
423 }
424
425 void ClientConnection::On(const Packet::Part &) {
426         conn.Close();
427 }
428
429 void ClientConnection::On(const Packet::PlayerUpdate &pack) {
430         if (!HasPlayer()) return;
431         int pack_diff = int16_t(pack.Seq()) - int16_t(player_update_pack);
432         bool overdue = player_update_timer.HitOnce();
433         player_update_timer.Reset();
434         if (pack_diff > 0 || overdue) {
435                 player_update_pack = pack.Seq();
436                 pack.ReadPlayerState(player_update_state);
437                 // accept velocity and orientation as "user input"
438                 PlayerEntity().Velocity(player_update_state.velocity);
439                 PlayerEntity().Orientation(player_update_state.orient);
440         }
441 }
442
443
444 Connection::Connection(const IPaddress &addr)
445 : handler(nullptr)
446 , addr(addr)
447 , send_timer(500)
448 , recv_timer(10000)
449 , ctrl_out{ 0, 0xFFFF, 0xFFFFFFFF }
450 , ctrl_in{ 0, 0xFFFF, 0xFFFFFFFF }
451 , closed(false) {
452         send_timer.Start();
453         recv_timer.Start();
454 }
455
456 bool Connection::Matches(const IPaddress &remote) const noexcept {
457         return memcmp(&addr, &remote, sizeof(IPaddress)) == 0;
458 }
459
460 void Connection::FlagSend() noexcept {
461         send_timer.Reset();
462 }
463
464 void Connection::FlagRecv() noexcept {
465         recv_timer.Reset();
466 }
467
468 bool Connection::ShouldPing() const noexcept {
469         return !closed && send_timer.HitOnce();
470 }
471
472 bool Connection::TimedOut() const noexcept {
473         return recv_timer.HitOnce();
474 }
475
476 void Connection::Update(int dt) {
477         send_timer.Update(dt);
478         recv_timer.Update(dt);
479         if (TimedOut()) {
480                 Close();
481                 if (HasHandler()) {
482                         Handler().OnTimeout();
483                 }
484         }
485 }
486
487
488 uint16_t Connection::Send(UDPpacket &udp_pack, UDPsocket sock) {
489         Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
490         pack.header.ctrl = ctrl_out;
491         uint16_t seq = ctrl_out.seq++;
492
493         udp_pack.address = addr;
494         if (SDLNet_UDP_Send(sock, -1, &udp_pack) == 0) {
495                 throw NetError("SDLNet_UDP_Send");
496         }
497
498         FlagSend();
499         return seq;
500 }
501
502 void Connection::Received(const UDPpacket &udp_pack) {
503         Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
504
505         // ack to the remote
506         int16_t diff = int16_t(pack.header.ctrl.seq) - int16_t(ctrl_out.ack);
507         if (diff > 0) {
508                 if (diff >= 32) {
509                         ctrl_out.hist = 0;
510                 } else {
511                         ctrl_out.hist <<= diff;
512                         ctrl_out.hist |= 1 << (diff - 1);
513                 }
514         } else if (diff < 0 && diff >= -32) {
515                 ctrl_out.hist |= 1 << (-diff - 1);
516         }
517         ctrl_out.ack = pack.header.ctrl.seq;
518         FlagRecv();
519
520         if (!HasHandler()) {
521                 return;
522         }
523
524         Packet::TControl ctrl_new = pack.header.ctrl;
525         Handler().Handle(udp_pack);
526
527         if (diff > 0) {
528                 // if the packet holds more recent information
529                 // check if remote failed to ack one of our packets
530                 diff = int16_t(ctrl_new.ack) - int16_t(ctrl_in.ack);
531                 // should always be true, but you never know…
532                 if (diff > 0) {
533                         for (int i = 0; i < diff; ++i) {
534                                 if (i > 32 || (i < 32 && (ctrl_in.hist & (1 << (31 - i))) == 0)) {
535                                         Handler().OnPacketLost(ctrl_in.ack - 32 + i);
536                                 }
537                         }
538                 }
539                 // check for newly ack'd packets
540                 for (uint16_t s = ctrl_new.AckBegin(); s != ctrl_new.AckEnd(); --s) {
541                         if (ctrl_new.Acks(s) && !ctrl_in.Acks(s)) {
542                                 Handler().OnPacketReceived(s);
543                         }
544                 }
545                 ctrl_in = ctrl_new;
546         }
547 }
548
549 bool Packet::TControl::Acks(uint16_t s) const noexcept {
550         int16_t diff = int16_t(ack) - int16_t(s);
551         if (diff == 0) return true;
552         if (diff < 0 || diff > 32) return false;
553         return (hist & (1 << (diff - 1))) != 0;
554 }
555
556 uint16_t Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) {
557         Packet::Make<Packet::Ping>(udp_pack);
558         return Send(udp_pack, sock);
559 }
560
561
562 ostream &operator <<(ostream &out, const IPaddress &addr) {
563         const unsigned char *host = reinterpret_cast<const unsigned char *>(&addr.host);
564         out << int(host[0])
565                 << '.' << int(host[1])
566                 << '.' << int(host[2])
567                 << '.' << int(host[3]);
568         if (addr.port) {
569                 out << ':' << SDLNet_Read16(&addr.port);
570         }
571         return out;
572 }
573
574
575 const char *Packet::Type2String(uint8_t t) noexcept {
576         switch (t) {
577                 case Ping::TYPE:
578                         return "Ping";
579                 case Login::TYPE:
580                         return "Login";
581                 case Join::TYPE:
582                         return "Join";
583                 case Part::TYPE:
584                         return "Part";
585                 case PlayerUpdate::TYPE:
586                         return "PlayerUpdate";
587                 case SpawnEntity::TYPE:
588                         return "SpawnEntity";
589                 case DespawnEntity::TYPE:
590                         return "DespawnEntity";
591                 case EntityUpdate::TYPE:
592                         return "EntityUpdate";
593                 case PlayerCorrection::TYPE:
594                         return "PlayerCorrection";
595                 case ChunkBegin::TYPE:
596                         return "ChunkBegin";
597                 case ChunkData::TYPE:
598                         return "ChunkData";
599                 default:
600                         return "Unknown";
601         }
602 }
603
604 template<class T>
605 void Packet::Payload::Write(const T &src, size_t off) noexcept {
606         if ((length - off) < sizeof(T)) {
607                 // dismiss out of bounds write
608                 return;
609         }
610         *reinterpret_cast<T *>(&data[off]) = src;
611 }
612
613 template<class T>
614 void Packet::Payload::Read(T &dst, size_t off) const noexcept {
615         if ((length - off) < sizeof(T)) {
616                 // dismiss out of bounds read
617                 return;
618         }
619         dst = *reinterpret_cast<T *>(&data[off]);
620 }
621
622 void Packet::Payload::WriteString(const string &src, size_t off, size_t maxlen) noexcept {
623         uint8_t *dst = &data[off];
624         size_t len = min(maxlen, length - off);
625         if (src.size() < len) {
626                 memset(dst, '\0', len);
627                 memcpy(dst, src.c_str(), src.size());
628         } else {
629                 memcpy(dst, src.c_str(), len);
630         }
631 }
632
633 void Packet::Payload::ReadString(string &dst, size_t off, size_t maxlen) const noexcept {
634         size_t len = min(maxlen, length - off);
635         dst.clear();
636         dst.reserve(len);
637         for (size_t i = 0; i < len && data[off + i] != '\0'; ++i) {
638                 dst.push_back(data[off + i]);
639         }
640 }
641
642
643 void Packet::Login::WritePlayerName(const string &name) noexcept {
644         WriteString(name, 0, 32);
645 }
646
647 void Packet::Login::ReadPlayerName(string &name) const noexcept {
648         ReadString(name, 0, 32);
649 }
650
651 void Packet::Join::WritePlayer(const Entity &player) noexcept {
652         Write(player.ID(), 0);
653         Write(player.GetState(), 4);
654 }
655
656 void Packet::Join::ReadPlayerID(uint32_t &id) const noexcept {
657         Read(id, 0);
658 }
659
660 void Packet::Join::ReadPlayerState(EntityState &state) const noexcept {
661         Read(state, 4);
662 }
663
664 void Packet::Join::WriteWorldName(const string &name) noexcept {
665         WriteString(name, 68, 32);
666 }
667
668 void Packet::Join::ReadWorldName(string &name) const noexcept {
669         ReadString(name, 68, 32);
670 }
671
672 void Packet::PlayerUpdate::WritePlayer(const Entity &player) noexcept {
673         Write(player.GetState(), 0);
674 }
675
676 void Packet::PlayerUpdate::ReadPlayerState(EntityState &state) const noexcept {
677         Read(state, 0);
678 }
679
680 void Packet::SpawnEntity::WriteEntity(const Entity &e) noexcept {
681         Write(e.ID(), 0);
682         if (e.GetModel()) {
683                 Write(e.GetModel().GetModel().ID(), 4);
684         } else {
685                 Write(uint32_t(0), 4);
686         }
687         Write(e.GetState(), 8);
688         Write(e.Bounds(), 72);
689         uint32_t flags = 0;
690         if (e.WorldCollidable()) {
691                 flags |= 1;
692         }
693         Write(flags, 96);
694         WriteString(e.Name(), 100, 32);
695 }
696
697 void Packet::SpawnEntity::ReadEntityID(uint32_t &id) const noexcept {
698         Read(id, 0);
699 }
700
701 void Packet::SpawnEntity::ReadSkeletonID(uint32_t &id) const noexcept {
702         Read(id, 4);
703 }
704
705 void Packet::SpawnEntity::ReadEntity(Entity &e) const noexcept {
706         EntityState state;
707         AABB bounds;
708         uint32_t flags = 0;
709         string name;
710
711         Read(state, 8);
712         Read(bounds, 72);
713         Read(flags, 96);
714         ReadString(name, 100, 32);
715
716         e.SetState(state);
717         e.Bounds(bounds);
718         e.WorldCollidable(flags & 1);
719         e.Name(name);
720 }
721
722 void Packet::DespawnEntity::WriteEntityID(uint32_t id) noexcept {
723         Write(id, 0);
724 }
725
726 void Packet::DespawnEntity::ReadEntityID(uint32_t &id) const noexcept {
727         Read(id, 0);
728 }
729
730 void Packet::EntityUpdate::WriteEntityCount(uint32_t count) noexcept {
731         Write(count, 0);
732 }
733
734 void Packet::EntityUpdate::ReadEntityCount(uint32_t &count) const noexcept {
735         Read(count, 0);
736 }
737
738 void Packet::EntityUpdate::WriteEntity(const Entity &entity, uint32_t num) noexcept {
739         uint32_t off = 4 + (num * 64);
740
741         Write(entity.ID(), off);
742         Write(entity.GetState(), off + 4);
743 }
744
745 void Packet::EntityUpdate::ReadEntityID(uint32_t &id, uint32_t num) const noexcept {
746         Read(id, 4 + (num * 64));
747 }
748
749 void Packet::EntityUpdate::ReadEntityState(EntityState &state, uint32_t num) const noexcept {
750         uint32_t off = 4 + (num * 64);
751         Read(state, off + 4);
752 }
753
754 void Packet::PlayerCorrection::WritePacketSeq(std::uint16_t s) noexcept {
755         Write(s, 0);
756 }
757
758 void Packet::PlayerCorrection::ReadPacketSeq(std::uint16_t &s) const noexcept {
759         Read(s, 0);
760 }
761
762 void Packet::PlayerCorrection::WritePlayer(const Entity &player) noexcept {
763         Write(player.GetState(), 2);
764 }
765
766 void Packet::PlayerCorrection::ReadPlayerState(EntityState &state) const noexcept {
767         Read(state, 2);
768 }
769
770 void Packet::ChunkBegin::WriteTransmissionId(uint32_t id) noexcept {
771         Write(id, 0);
772 }
773
774 void Packet::ChunkBegin::ReadTransmissionId(uint32_t &id) const noexcept {
775         Read(id, 0);
776 }
777
778 void Packet::ChunkBegin::WriteFlags(uint32_t f) noexcept {
779         Write(f, 4);
780 }
781
782 void Packet::ChunkBegin::ReadFlags(uint32_t &f) const noexcept {
783         Read(f, 4);
784 }
785
786 void Packet::ChunkBegin::WriteChunkCoords(const glm::ivec3 &pos) noexcept {
787         Write(pos, 8);
788 }
789
790 void Packet::ChunkBegin::ReadChunkCoords(glm::ivec3 &pos) const noexcept {
791         Read(pos, 8);
792 }
793
794 void Packet::ChunkBegin::WriteDataSize(uint32_t s) noexcept {
795         Write(s, 20);
796 }
797
798 void Packet::ChunkBegin::ReadDataSize(uint32_t &s) const noexcept {
799         Read(s, 20);
800 }
801
802 void Packet::ChunkData::WriteTransmissionId(uint32_t id) noexcept {
803         Write(id, 0);
804 }
805
806 void Packet::ChunkData::ReadTransmissionId(uint32_t &id) const noexcept {
807         Read(id, 0);
808 }
809
810 void Packet::ChunkData::WriteDataOffset(uint32_t o) noexcept {
811         Write(o, 4);
812 }
813
814 void Packet::ChunkData::ReadDataOffset(uint32_t &o) const noexcept {
815         Read(o, 4);
816 }
817
818 void Packet::ChunkData::WriteDataSize(uint32_t s) noexcept {
819         Write(s, 8);
820 }
821
822 void Packet::ChunkData::ReadDataSize(uint32_t &s) const noexcept {
823         Read(s, 8);
824 }
825
826 void Packet::ChunkData::WriteData(const uint8_t *d, size_t l) noexcept {
827         size_t len = min(length - 12, l);
828         memcpy(&data[12], d, len);
829 }
830
831 void Packet::ChunkData::ReadData(uint8_t *d, size_t l) const noexcept {
832         size_t len = min(length - 12, l);
833         memcpy(d, &data[12], len);
834 }
835
836
837 void ConnectionHandler::Handle(const UDPpacket &udp_pack) {
838         const Packet &pack = *reinterpret_cast<const Packet *>(udp_pack.data);
839         switch (pack.Type()) {
840                 case Packet::Ping::TYPE:
841                         On(Packet::As<Packet::Ping>(udp_pack));
842                         break;
843                 case Packet::Login::TYPE:
844                         On(Packet::As<Packet::Login>(udp_pack));
845                         break;
846                 case Packet::Join::TYPE:
847                         On(Packet::As<Packet::Join>(udp_pack));
848                         break;
849                 case Packet::Part::TYPE:
850                         On(Packet::As<Packet::Part>(udp_pack));
851                         break;
852                 case Packet::PlayerUpdate::TYPE:
853                         On(Packet::As<Packet::PlayerUpdate>(udp_pack));
854                         break;
855                 case Packet::SpawnEntity::TYPE:
856                         On(Packet::As<Packet::SpawnEntity>(udp_pack));
857                         break;
858                 case Packet::DespawnEntity::TYPE:
859                         On(Packet::As<Packet::DespawnEntity>(udp_pack));
860                         break;
861                 case Packet::EntityUpdate::TYPE:
862                         On(Packet::As<Packet::EntityUpdate>(udp_pack));
863                         break;
864                 case Packet::PlayerCorrection::TYPE:
865                         On(Packet::As<Packet::PlayerCorrection>(udp_pack));
866                         break;
867                 case Packet::ChunkBegin::TYPE:
868                         On(Packet::As<Packet::ChunkBegin>(udp_pack));
869                         break;
870                 case Packet::ChunkData::TYPE:
871                         On(Packet::As<Packet::ChunkData>(udp_pack));
872                         break;
873                 default:
874                         // drop unknown or unhandled packets
875                         break;
876         }
877 }
878
879
880 Server::Server(const Config &conf, World &world)
881 : serv_sock(nullptr)
882 , serv_pack{ -1, nullptr, 0 }
883 , clients()
884 , world(world) {
885         serv_sock = SDLNet_UDP_Open(conf.port);
886         if (!serv_sock) {
887                 throw NetError("SDLNet_UDP_Open");
888         }
889
890         serv_pack.data = new Uint8[sizeof(Packet)];
891         serv_pack.maxlen = sizeof(Packet);
892 }
893
894 Server::~Server() {
895         delete[] serv_pack.data;
896         SDLNet_UDP_Close(serv_sock);
897 }
898
899
900 void Server::Handle() {
901         int result = SDLNet_UDP_Recv(serv_sock, &serv_pack);
902         while (result > 0) {
903                 HandlePacket(serv_pack);
904                 result = SDLNet_UDP_Recv(serv_sock, &serv_pack);
905         }
906         if (result == -1) {
907                 // a boo boo happened
908                 throw NetError("SDLNet_UDP_Recv");
909         }
910 }
911
912 void Server::HandlePacket(const UDPpacket &udp_pack) {
913         if (udp_pack.len < int(sizeof(Packet::Header))) {
914                 // packet too small, drop
915                 return;
916         }
917         const Packet &pack = *reinterpret_cast<const Packet *>(udp_pack.data);
918         if (pack.header.tag != Packet::TAG) {
919                 // mistagged packet, drop
920                 return;
921         }
922
923         ClientConnection &client = GetClient(udp_pack.address);
924         client.GetConnection().Received(udp_pack);
925 }
926
927 ClientConnection &Server::GetClient(const IPaddress &addr) {
928         for (ClientConnection &client : clients) {
929                 if (client.Matches(addr)) {
930                         return client;
931                 }
932         }
933         clients.emplace_back(*this, addr);
934         return clients.back();
935 }
936
937 void Server::Update(int dt) {
938         for (list<ClientConnection>::iterator client(clients.begin()), end(clients.end()); client != end;) {
939                 client->Update(dt);
940                 if (client->Disconnected()) {
941                         client = clients.erase(client);
942                 } else {
943                         ++client;
944                 }
945         }
946 }
947
948 }