]> git.localhorst.tv Git - blank.git/blob - src/net/net.cpp
grouped entity physics state into a struct
[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/Entity.hpp"
12 #include "../world/EntityState.hpp"
13 #include "../world/World.hpp"
14
15 #include <cstring>
16 #include <iostream>
17 #include <glm/gtx/io.hpp>
18
19 using namespace std;
20
21
22 namespace blank {
23
24 constexpr size_t Packet::Ping::MAX_LEN;
25 constexpr size_t Packet::Login::MAX_LEN;
26 constexpr size_t Packet::Join::MAX_LEN;
27 constexpr size_t Packet::Part::MAX_LEN;
28 constexpr size_t Packet::PlayerUpdate::MAX_LEN;
29 constexpr size_t Packet::SpawnEntity::MAX_LEN;
30 constexpr size_t Packet::DespawnEntity::MAX_LEN;
31 constexpr size_t Packet::EntityUpdate::MAX_LEN;
32
33 namespace {
34
35 UDPsocket client_bind(Uint16 port) {
36         UDPsocket sock = SDLNet_UDP_Open(port);
37         if (!sock) {
38                 throw NetError("SDLNet_UDP_Open");
39         }
40         return sock;
41 }
42
43 IPaddress client_resolve(const char *host, Uint16 port) {
44         IPaddress addr;
45         if (SDLNet_ResolveHost(&addr, host, port) != 0) {
46                 throw NetError("SDLNet_ResolveHost");
47         }
48         return addr;
49 }
50
51 }
52
53 Client::Client(const Config &conf)
54 : conn(client_resolve(conf.host.c_str(), conf.port))
55 , client_sock(client_bind(0))
56 , client_pack{ -1, nullptr, 0 } {
57         client_pack.data = new Uint8[sizeof(Packet)];
58         client_pack.maxlen = sizeof(Packet);
59         // establish connection
60         SendPing();
61 }
62
63 Client::~Client() {
64         delete[] client_pack.data;
65         SDLNet_UDP_Close(client_sock);
66 }
67
68
69 void Client::Handle() {
70         int result = SDLNet_UDP_Recv(client_sock, &client_pack);
71         while (result > 0) {
72                 HandlePacket(client_pack);
73                 result = SDLNet_UDP_Recv(client_sock, &client_pack);
74         }
75         if (result == -1) {
76                 // a boo boo happened
77                 throw NetError("SDLNet_UDP_Recv");
78         }
79 }
80
81 void Client::HandlePacket(const UDPpacket &udp_pack) {
82         if (!conn.Matches(udp_pack.address)) {
83                 // packet came from somewhere else, drop
84                 return;
85         }
86         const Packet &pack = *reinterpret_cast<const Packet *>(udp_pack.data);
87         if (pack.header.tag != Packet::TAG) {
88                 // mistagged packet, drop
89                 return;
90         }
91
92         conn.Received(udp_pack);
93 }
94
95 void Client::Update(int dt) {
96         conn.Update(dt);
97         if (conn.ShouldPing()) {
98                 SendPing();
99         }
100 }
101
102 uint16_t Client::SendPing() {
103         return conn.SendPing(client_pack, client_sock);
104 }
105
106 uint16_t Client::SendLogin(const string &name) {
107         auto pack = Packet::Make<Packet::Login>(client_pack);
108         pack.WritePlayerName(name);
109         return conn.Send(client_pack, client_sock);
110 }
111
112 uint16_t Client::SendPlayerUpdate(const Entity &player) {
113         auto pack = Packet::Make<Packet::PlayerUpdate>(client_pack);
114         pack.WritePlayer(player);
115         return conn.Send(client_pack, client_sock);
116 }
117
118 uint16_t Client::SendPart() {
119         Packet::Make<Packet::Part>(client_pack);
120         return conn.Send(client_pack, client_sock);
121 }
122
123
124 ClientConnection::ClientConnection(Server &server, const IPaddress &addr)
125 : server(server)
126 , conn(addr)
127 , player(nullptr)
128 , spawns()
129 , confirm_wait(0)
130 , player_update_pack(0)
131 , player_update_timer(1500) {
132         conn.SetHandler(this);
133 }
134
135 ClientConnection::~ClientConnection() {
136         DetachPlayer();
137 }
138
139 void ClientConnection::Update(int dt) {
140         conn.Update(dt);
141         if (Disconnected()) {
142                 return;
143         }
144         if (HasPlayer()) {
145                 // sync entities
146                 auto global_iter = server.GetWorld().Entities().begin();
147                 auto global_end = server.GetWorld().Entities().end();
148                 auto local_iter = spawns.begin();
149                 auto local_end = spawns.end();
150
151                 while (global_iter != global_end && local_iter != local_end) {
152                         if (global_iter->ID() == local_iter->entity->ID()) {
153                                 // they're the same
154                                 if (CanDespawn(*global_iter)) {
155                                         SendDespawn(*local_iter);
156                                 } else {
157                                         // update
158                                         SendUpdate(*local_iter);
159                                 }
160                                 ++global_iter;
161                                 ++local_iter;
162                         } else if (global_iter->ID() < local_iter->entity->ID()) {
163                                 // global entity was inserted
164                                 if (CanSpawn(*global_iter)) {
165                                         auto spawned = spawns.emplace(local_iter, *global_iter);
166                                         SendSpawn(*spawned);
167                                 }
168                                 ++global_iter;
169                         } else {
170                                 // global entity was removed
171                                 SendDespawn(*local_iter);
172                                 ++local_iter;
173                         }
174                 }
175
176                 // leftover spawns
177                 while (global_iter != global_end) {
178                         if (CanSpawn(*global_iter)) {
179                                 spawns.emplace_back(*global_iter);
180                                 SendSpawn(spawns.back());
181                         }
182                         ++global_iter;
183                 }
184
185                 // leftover despawns
186                 while (local_iter != local_end) {
187                         SendDespawn(*local_iter);
188                         ++local_iter;
189                 }
190         }
191         if (conn.ShouldPing()) {
192                 conn.SendPing(server.GetPacket(), server.GetSocket());
193         }
194 }
195
196 ClientConnection::SpawnStatus::SpawnStatus(Entity &e)
197 : entity(&e)
198 , spawn_pack(-1)
199 , despawn_pack(-1) {
200         entity->Ref();
201 }
202
203 ClientConnection::SpawnStatus::~SpawnStatus() {
204         entity->UnRef();
205 }
206
207 bool ClientConnection::CanSpawn(const Entity &e) const noexcept {
208         return
209                 &e != player &&
210                 !e.Dead() &&
211                 manhattan_radius(e.ChunkCoords() - Player().ChunkCoords()) < 7;
212 }
213
214 bool ClientConnection::CanDespawn(const Entity &e) const noexcept {
215         return
216                 e.Dead() ||
217                 manhattan_radius(e.ChunkCoords() - Player().ChunkCoords()) > 7;
218 }
219
220 void ClientConnection::SendSpawn(SpawnStatus &status) {
221         // don't double spawn
222         if (status.spawn_pack != -1) return;
223
224         auto pack = Packet::Make<Packet::SpawnEntity>(server.GetPacket());
225         pack.WriteEntity(*status.entity);
226         status.spawn_pack = conn.Send(server.GetPacket(), server.GetSocket());
227         ++confirm_wait;
228 }
229
230 void ClientConnection::SendDespawn(SpawnStatus &status) {
231         // don't double despawn
232         if (status.despawn_pack != -1) return;
233
234         auto pack = Packet::Make<Packet::DespawnEntity>(server.GetPacket());
235         pack.WriteEntityID(status.entity->ID());
236         status.despawn_pack = conn.Send(server.GetPacket(), server.GetSocket());
237         ++confirm_wait;
238 }
239
240 void ClientConnection::SendUpdate(SpawnStatus &status) {
241         // don't send updates while spawn not ack'd or despawn sent
242         if (status.spawn_pack != -1 || status.despawn_pack != -1) return;
243
244         // TODO: pack entity updates
245         auto pack = Packet::Make<Packet::EntityUpdate>(server.GetPacket());
246         pack.WriteEntityCount(1);
247         pack.WriteEntity(*status.entity, 0);
248         server.GetPacket().len = Packet::EntityUpdate::GetSize(1);
249         conn.Send(server.GetPacket(), server.GetSocket());
250 }
251
252 void ClientConnection::AttachPlayer(Entity &new_player) {
253         DetachPlayer();
254         player = &new_player;
255         player->Ref();
256         cout << "player \"" << player->Name() << "\" joined" << endl;
257 }
258
259 void ClientConnection::DetachPlayer() {
260         if (!player) return;
261         player->Kill();
262         player->UnRef();
263         cout << "player \"" << player->Name() << "\" left" << endl;
264         player = nullptr;
265 }
266
267 void ClientConnection::OnPacketReceived(uint16_t seq) {
268         if (!confirm_wait) return;
269         for (auto iter = spawns.begin(), end = spawns.end(); iter != end; ++iter) {
270                 if (seq == iter->spawn_pack) {
271                         iter->spawn_pack = -1;
272                         --confirm_wait;
273                         return;
274                 }
275                 if (seq == iter->despawn_pack) {
276                         spawns.erase(iter);
277                         --confirm_wait;
278                         return;
279                 }
280         }
281 }
282
283 void ClientConnection::OnPacketLost(uint16_t seq) {
284         if (!confirm_wait) return;
285         for (SpawnStatus &status : spawns) {
286                 if (seq == status.spawn_pack) {
287                         status.spawn_pack = -1;
288                         --confirm_wait;
289                         SendSpawn(status);
290                         return;
291                 }
292                 if (seq == status.despawn_pack) {
293                         status.despawn_pack = -1;
294                         --confirm_wait;
295                         SendDespawn(status);
296                         return;
297                 }
298         }
299 }
300
301 void ClientConnection::On(const Packet::Login &pack) {
302         string name;
303         pack.ReadPlayerName(name);
304
305         Entity *new_player = server.GetWorld().AddPlayer(name).entity;
306
307         if (new_player) {
308                 // success!
309                 AttachPlayer(*new_player);
310                 cout << "accepted login from player \"" << name << '"' << endl;
311                 auto response = Packet::Make<Packet::Join>(server.GetPacket());
312                 response.WritePlayer(*new_player);
313                 response.WriteWorldName(server.GetWorld().Name());
314                 conn.Send(server.GetPacket(), server.GetSocket());
315                 // set up update tracking
316                 player_update_pack = pack.Seq();
317                 player_update_timer.Reset();
318                 player_update_timer.Start();
319         } else {
320                 // aw no :(
321                 cout << "rejected login from player \"" << name << '"' << endl;
322                 Packet::Make<Packet::Part>(server.GetPacket());
323                 conn.Send(server.GetPacket(), server.GetSocket());
324                 conn.Close();
325         }
326 }
327
328 void ClientConnection::On(const Packet::Part &) {
329         conn.Close();
330 }
331
332 void ClientConnection::On(const Packet::PlayerUpdate &pack) {
333         if (!HasPlayer()) return;
334         int pack_diff = int16_t(pack.Seq()) - int16_t(player_update_pack);
335         bool overdue = player_update_timer.HitOnce();
336         player_update_timer.Reset();
337         if (pack_diff > 0 || overdue) {
338                 player_update_pack = pack.Seq();
339                 // TODO: do client input validation here
340                 pack.ReadPlayerState(Player().GetState());
341         }
342 }
343
344
345 Connection::Connection(const IPaddress &addr)
346 : handler(nullptr)
347 , addr(addr)
348 , send_timer(500)
349 , recv_timer(10000)
350 , ctrl_out{ 0, 0xFFFF, 0xFFFFFFFF }
351 , ctrl_in{ 0, 0xFFFF, 0xFFFFFFFF }
352 , closed(false) {
353         send_timer.Start();
354         recv_timer.Start();
355 }
356
357 bool Connection::Matches(const IPaddress &remote) const noexcept {
358         return memcmp(&addr, &remote, sizeof(IPaddress)) == 0;
359 }
360
361 void Connection::FlagSend() noexcept {
362         send_timer.Reset();
363 }
364
365 void Connection::FlagRecv() noexcept {
366         recv_timer.Reset();
367 }
368
369 bool Connection::ShouldPing() const noexcept {
370         return !closed && send_timer.HitOnce();
371 }
372
373 bool Connection::TimedOut() const noexcept {
374         return recv_timer.HitOnce();
375 }
376
377 void Connection::Update(int dt) {
378         send_timer.Update(dt);
379         recv_timer.Update(dt);
380         if (TimedOut()) {
381                 Close();
382                 if (HasHandler()) {
383                         Handler().OnTimeout();
384                 }
385         }
386 }
387
388
389 uint16_t Connection::Send(UDPpacket &udp_pack, UDPsocket sock) {
390         Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
391         pack.header.ctrl = ctrl_out;
392         uint16_t seq = ctrl_out.seq++;
393
394         udp_pack.address = addr;
395         if (SDLNet_UDP_Send(sock, -1, &udp_pack) == 0) {
396                 throw NetError("SDLNet_UDP_Send");
397         }
398
399         FlagSend();
400         return seq;
401 }
402
403 void Connection::Received(const UDPpacket &udp_pack) {
404         Packet &pack = *reinterpret_cast<Packet *>(udp_pack.data);
405
406         // ack to the remote
407         int16_t diff = int16_t(pack.header.ctrl.seq) - int16_t(ctrl_out.ack);
408         if (diff > 0) {
409                 if (diff >= 32) {
410                         ctrl_out.hist = 0;
411                 } else {
412                         ctrl_out.hist <<= diff;
413                         ctrl_out.hist |= 1 << (diff - 1);
414                 }
415         } else if (diff < 0 && diff >= -32) {
416                 ctrl_out.hist |= 1 << (-diff - 1);
417         }
418         ctrl_out.ack = pack.header.ctrl.seq;
419         FlagRecv();
420
421         if (!HasHandler()) {
422                 return;
423         }
424
425         Packet::TControl ctrl_new = pack.header.ctrl;
426         Handler().Handle(udp_pack);
427
428         if (diff > 0) {
429                 // if the packet holds more recent information
430                 // check if remote failed to ack one of our packets
431                 diff = int16_t(ctrl_new.ack) - int16_t(ctrl_in.ack);
432                 // should always be true, but you never know…
433                 if (diff > 0) {
434                         for (int i = 0; i < diff; ++i) {
435                                 if (i > 32 || (i < 32 && (ctrl_in.hist & (1 << (31 - i))) == 0)) {
436                                         Handler().OnPacketLost(ctrl_in.ack - 32 + i);
437                                 }
438                         }
439                 }
440                 // check for newly ack'd packets
441                 for (uint16_t s = ctrl_new.AckBegin(); s != ctrl_new.AckEnd(); ++s) {
442                         if (ctrl_new.Acks(s) && !ctrl_in.Acks(s)) {
443                                 Handler().OnPacketReceived(s);
444                         }
445                 }
446                 ctrl_in = ctrl_new;
447         }
448 }
449
450 bool Packet::TControl::Acks(uint16_t s) const noexcept {
451         int16_t diff = int16_t(ack) - int16_t(s);
452         if (diff == 0) return true;
453         if (diff < 0 || diff > 32) return false;
454         return (hist & (1 << (diff - 1))) != 0;
455 }
456
457 uint16_t Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) {
458         Packet::Make<Packet::Ping>(udp_pack);
459         return Send(udp_pack, sock);
460 }
461
462
463 ostream &operator <<(ostream &out, const IPaddress &addr) {
464         const unsigned char *host = reinterpret_cast<const unsigned char *>(&addr.host);
465         out << int(host[0])
466                 << '.' << int(host[1])
467                 << '.' << int(host[2])
468                 << '.' << int(host[3]);
469         if (addr.port) {
470                 out << ':' << SDLNet_Read16(&addr.port);
471         }
472         return out;
473 }
474
475
476 const char *Packet::Type2String(uint8_t t) noexcept {
477         switch (t) {
478                 case Ping::TYPE:
479                         return "Ping";
480                 case Login::TYPE:
481                         return "Login";
482                 case Join::TYPE:
483                         return "Join";
484                 case Part::TYPE:
485                         return "Part";
486                 case PlayerUpdate::TYPE:
487                         return "PlayerUpdate";
488                 case SpawnEntity::TYPE:
489                         return "SpawnEntity";
490                 case DespawnEntity::TYPE:
491                         return "DespawnEntity";
492                 case EntityUpdate::TYPE:
493                         return "EntityUpdate";
494                 default:
495                         return "Unknown";
496         }
497 }
498
499 template<class T>
500 void Packet::Payload::Write(const T &src, size_t off) noexcept {
501         if ((length - off) < sizeof(T)) {
502                 // dismiss out of bounds write
503                 return;
504         }
505         *reinterpret_cast<T *>(&data[off]) = src;
506 }
507
508 template<class T>
509 void Packet::Payload::Read(T &dst, size_t off) const noexcept {
510         if ((length - off) < sizeof(T)) {
511                 // dismiss out of bounds read
512                 return;
513         }
514         dst = *reinterpret_cast<T *>(&data[off]);
515 }
516
517 void Packet::Payload::WriteString(const string &src, size_t off, size_t maxlen) noexcept {
518         uint8_t *dst = &data[off];
519         size_t len = min(maxlen, length - off);
520         if (src.size() < len) {
521                 memset(dst, '\0', len);
522                 memcpy(dst, src.c_str(), src.size());
523         } else {
524                 memcpy(dst, src.c_str(), len);
525         }
526 }
527
528 void Packet::Payload::ReadString(string &dst, size_t off, size_t maxlen) const noexcept {
529         size_t len = min(maxlen, length - off);
530         dst.clear();
531         dst.reserve(len);
532         for (size_t i = 0; i < len && data[off + i] != '\0'; ++i) {
533                 dst.push_back(data[off + i]);
534         }
535 }
536
537
538 void Packet::Login::WritePlayerName(const string &name) noexcept {
539         WriteString(name, 0, 32);
540 }
541
542 void Packet::Login::ReadPlayerName(string &name) const noexcept {
543         ReadString(name, 0, 32);
544 }
545
546 void Packet::Join::WritePlayer(const Entity &player) noexcept {
547         Write(player.ID(), 0);
548         Write(player.GetState(), 4);
549 }
550
551 void Packet::Join::ReadPlayerID(uint32_t &id) const noexcept {
552         Read(id, 0);
553 }
554
555 void Packet::Join::ReadPlayerState(EntityState &state) const noexcept {
556         Read(state, 4);
557 }
558
559 void Packet::Join::WriteWorldName(const string &name) noexcept {
560         WriteString(name, 68, 32);
561 }
562
563 void Packet::Join::ReadWorldName(string &name) const noexcept {
564         ReadString(name, 68, 32);
565 }
566
567 void Packet::PlayerUpdate::WritePlayer(const Entity &player) noexcept {
568         Write(player.GetState(), 0);
569 }
570
571 void Packet::PlayerUpdate::ReadPlayerState(EntityState &state) const noexcept {
572         Read(state, 0);
573 }
574
575 void Packet::SpawnEntity::WriteEntity(const Entity &e) noexcept {
576         Write(e.ID(), 0);
577         if (e.GetModel()) {
578                 Write(e.GetModel().GetModel().ID(), 4);
579         } else {
580                 Write(uint32_t(0), 4);
581         }
582         Write(e.GetState(), 8);
583         Write(e.Bounds(), 72);
584         uint32_t flags = 0;
585         if (e.WorldCollidable()) {
586                 flags |= 1;
587         }
588         Write(flags, 96);
589         WriteString(e.Name(), 100, 32);
590 }
591
592 void Packet::SpawnEntity::ReadEntityID(uint32_t &id) const noexcept {
593         Read(id, 0);
594 }
595
596 void Packet::SpawnEntity::ReadSkeletonID(uint32_t &id) const noexcept {
597         Read(id, 4);
598 }
599
600 void Packet::SpawnEntity::ReadEntity(Entity &e) const noexcept {
601         EntityState state;
602         AABB bounds;
603         uint32_t flags = 0;
604         string name;
605
606         Read(state, 8);
607         Read(bounds, 72);
608         Read(flags, 96);
609         ReadString(name, 100, 32);
610
611         e.SetState(state);
612         e.Bounds(bounds);
613         e.WorldCollidable(flags & 1);
614         e.Name(name);
615 }
616
617 void Packet::DespawnEntity::WriteEntityID(uint32_t id) noexcept {
618         Write(id, 0);
619 }
620
621 void Packet::DespawnEntity::ReadEntityID(uint32_t &id) const noexcept {
622         Read(id, 0);
623 }
624
625 void Packet::EntityUpdate::WriteEntityCount(uint32_t count) noexcept {
626         Write(count, 0);
627 }
628
629 void Packet::EntityUpdate::ReadEntityCount(uint32_t &count) const noexcept {
630         Read(count, 0);
631 }
632
633 void Packet::EntityUpdate::WriteEntity(const Entity &entity, uint32_t num) noexcept {
634         uint32_t off = 4 + (num * 64);
635
636         Write(entity.ID(), off);
637         Write(entity.GetState(), off + 4);
638 }
639
640 void Packet::EntityUpdate::ReadEntityID(uint32_t &id, uint32_t num) const noexcept {
641         Read(id, 4 + (num * 64));
642 }
643
644 void Packet::EntityUpdate::ReadEntityState(EntityState &state, uint32_t num) const noexcept {
645         uint32_t off = 4 + (num * 64);
646         Read(state, off + 4);
647 }
648
649
650 void ConnectionHandler::Handle(const UDPpacket &udp_pack) {
651         const Packet &pack = *reinterpret_cast<const Packet *>(udp_pack.data);
652         switch (pack.Type()) {
653                 case Packet::Ping::TYPE:
654                         On(Packet::As<Packet::Ping>(udp_pack));
655                         break;
656                 case Packet::Login::TYPE:
657                         On(Packet::As<Packet::Login>(udp_pack));
658                         break;
659                 case Packet::Join::TYPE:
660                         On(Packet::As<Packet::Join>(udp_pack));
661                         break;
662                 case Packet::Part::TYPE:
663                         On(Packet::As<Packet::Part>(udp_pack));
664                         break;
665                 case Packet::PlayerUpdate::TYPE:
666                         On(Packet::As<Packet::PlayerUpdate>(udp_pack));
667                         break;
668                 case Packet::SpawnEntity::TYPE:
669                         On(Packet::As<Packet::SpawnEntity>(udp_pack));
670                         break;
671                 case Packet::DespawnEntity::TYPE:
672                         On(Packet::As<Packet::DespawnEntity>(udp_pack));
673                         break;
674                 case Packet::EntityUpdate::TYPE:
675                         On(Packet::As<Packet::EntityUpdate>(udp_pack));
676                         break;
677                 default:
678                         // drop unknown or unhandled packets
679                         break;
680         }
681 }
682
683
684 Server::Server(const Config &conf, World &world)
685 : serv_sock(nullptr)
686 , serv_pack{ -1, nullptr, 0 }
687 , clients()
688 , world(world) {
689         serv_sock = SDLNet_UDP_Open(conf.port);
690         if (!serv_sock) {
691                 throw NetError("SDLNet_UDP_Open");
692         }
693
694         serv_pack.data = new Uint8[sizeof(Packet)];
695         serv_pack.maxlen = sizeof(Packet);
696 }
697
698 Server::~Server() {
699         delete[] serv_pack.data;
700         SDLNet_UDP_Close(serv_sock);
701 }
702
703
704 void Server::Handle() {
705         int result = SDLNet_UDP_Recv(serv_sock, &serv_pack);
706         while (result > 0) {
707                 HandlePacket(serv_pack);
708                 result = SDLNet_UDP_Recv(serv_sock, &serv_pack);
709         }
710         if (result == -1) {
711                 // a boo boo happened
712                 throw NetError("SDLNet_UDP_Recv");
713         }
714 }
715
716 void Server::HandlePacket(const UDPpacket &udp_pack) {
717         if (udp_pack.len < int(sizeof(Packet::Header))) {
718                 // packet too small, drop
719                 return;
720         }
721         const Packet &pack = *reinterpret_cast<const Packet *>(udp_pack.data);
722         if (pack.header.tag != Packet::TAG) {
723                 // mistagged packet, drop
724                 return;
725         }
726
727         ClientConnection &client = GetClient(udp_pack.address);
728         client.GetConnection().Received(udp_pack);
729 }
730
731 ClientConnection &Server::GetClient(const IPaddress &addr) {
732         for (ClientConnection &client : clients) {
733                 if (client.Matches(addr)) {
734                         return client;
735                 }
736         }
737         clients.emplace_back(*this, addr);
738         return clients.back();
739 }
740
741 void Server::Update(int dt) {
742         for (list<ClientConnection>::iterator client(clients.begin()), end(clients.end()); client != end;) {
743                 client->Update(dt);
744                 if (client->Disconnected()) {
745                         client = clients.erase(client);
746                 } else {
747                         ++client;
748                 }
749         }
750 }
751
752 }