+uint16_t Client::SendPlayerUpdate(const Entity &player) {
+ auto pack = Packet::Make<Packet::PlayerUpdate>(client_pack);
+ pack.WritePlayer(player);
+ return conn.Send(client_pack, client_sock);
+}
+
+
+ClientConnection::ClientConnection(Server &server, const IPaddress &addr)
+: server(server)
+, conn(addr)
+, player(nullptr) {
+ conn.SetHandler(this);
+}
+
+ClientConnection::~ClientConnection() {
+ DetachPlayer();
+}
+
+void ClientConnection::Update(int dt) {
+ conn.Update(dt);
+ if (Disconnected()) {
+ cout << "disconnect from " << conn.Address() << endl;
+ } else if (conn.ShouldPing()) {
+ conn.SendPing(server.GetPacket(), server.GetSocket());
+ }
+}
+
+void ClientConnection::AttachPlayer(Entity &new_player) {
+ DetachPlayer();
+ player = &new_player;
+ player->Ref();
+}
+
+void ClientConnection::DetachPlayer() {
+ if (!player) return;
+ player->Kill();
+ player->UnRef();
+ player = nullptr;
+}
+
+void ClientConnection::On(const Packet::Login &pack) {
+ string name;
+ pack.ReadPlayerName(name);
+
+ Entity *new_player = server.GetWorld().AddPlayer(name);
+
+ if (new_player) {
+ // success!
+ AttachPlayer(*new_player);
+ cout << "accepted login from player \"" << name << '"' << endl;
+ auto response = Packet::Make<Packet::Join>(server.GetPacket());
+ response.WritePlayer(*new_player);
+ response.WriteWorldName(server.GetWorld().Name());
+ conn.Send(server.GetPacket(), server.GetSocket());
+ } else {
+ // aw no :(
+ cout << "rejected login from player \"" << name << '"' << endl;
+ Packet::Make<Packet::Part>(server.GetPacket());
+ conn.Send(server.GetPacket(), server.GetSocket());
+ conn.Close();
+ }
+}
+
+void ClientConnection::On(const Packet::Part &) {
+ conn.Close();
+}
+
+void ClientConnection::On(const Packet::PlayerUpdate &pack) {
+ if (!HasPlayer()) return;
+ pack.ReadPlayer(Player());
+}
+