From: Daniel Karbach Date: Sat, 5 Sep 2015 13:45:11 +0000 (+0200) Subject: make server aware connected clients' player entity X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=99345b497912db65204d48348140fc774dcb6989;p=blank.git make server aware connected clients' player entity --- diff --git a/src/net/ClientConnection.hpp b/src/net/ClientConnection.hpp new file mode 100644 index 0000000..acbee6e --- /dev/null +++ b/src/net/ClientConnection.hpp @@ -0,0 +1,44 @@ +#ifndef BLANK_NET_CLIENTCONNECTION_HPP_ +#define BLANK_NET_CLIENTCONNECTION_HPP_ + +#include "Connection.hpp" +#include "ConnectionHandler.hpp" + +#include + + +namespace blank { + +class Entity; +class Server; + +class ClientConnection +: public ConnectionHandler { + +public: + explicit ClientConnection(Server &, const IPaddress &); + ~ClientConnection(); + + bool Matches(const IPaddress &addr) const noexcept { return conn.Matches(addr); } + + void Update(int dt); + + Connection &GetConnection() noexcept { return conn; } + bool Disconnected() const noexcept { return conn.Closed(); } + + void AttachPlayer(Entity &); + void DetachPlayer(); + + void On(const Packet::Login &) override; + void On(const Packet::Part &) override; + +private: + Server &server; + Connection conn; + Entity *player; + +}; + +} + +#endif diff --git a/src/net/Server.hpp b/src/net/Server.hpp index a95cd37..a6d509b 100644 --- a/src/net/Server.hpp +++ b/src/net/Server.hpp @@ -7,7 +7,7 @@ namespace blank { -class Connection; +class ClientConnection; class World; class Server { @@ -25,21 +25,20 @@ public: void Update(int dt); -private: - void HandlePacket(const UDPpacket &); + UDPsocket &GetSocket() noexcept { return serv_sock; } + UDPpacket &GetPacket() noexcept { return serv_pack; } - Connection &GetClient(const IPaddress &); + World &GetWorld() noexcept { return world; } - void OnConnect(Connection &); - void OnDisconnect(Connection &); +private: + void HandlePacket(const UDPpacket &); - void HandleLogin(Connection &client, const UDPpacket &); - void HandlePart(Connection &client, const UDPpacket &); + ClientConnection &GetClient(const IPaddress &); private: UDPsocket serv_sock; UDPpacket serv_pack; - std::list clients; + std::list clients; World &world; diff --git a/src/net/net.cpp b/src/net/net.cpp index 4d36412..7f12e63 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -1,4 +1,5 @@ #include "Client.hpp" +#include "ClientConnection.hpp" #include "Connection.hpp" #include "ConnectionHandler.hpp" #include "io.hpp" @@ -101,6 +102,67 @@ uint16_t Client::SendLogin(const string &name) { } +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(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(server.GetPacket()); + conn.Send(server.GetPacket(), server.GetSocket()); + conn.Close(); + } +} + +void ClientConnection::On(const Packet::Part &) { + conn.Close(); +} + + Connection::Connection(const IPaddress &addr) : handler(nullptr) , addr(addr) @@ -387,85 +449,29 @@ void Server::HandlePacket(const UDPpacket &udp_pack) { return; } - Connection &client = GetClient(udp_pack.address); - client.Received(udp_pack); - - switch (pack.header.type) { - case Packet::Login::TYPE: - HandleLogin(client, udp_pack); - break; - case Packet::Part::TYPE: - HandlePart(client, udp_pack); - break; - default: - // just drop packets of unknown or unhandled type - break; - } + ClientConnection &client = GetClient(udp_pack.address); + client.GetConnection().Received(udp_pack); } -Connection &Server::GetClient(const IPaddress &addr) { - for (Connection &client : clients) { +ClientConnection &Server::GetClient(const IPaddress &addr) { + for (ClientConnection &client : clients) { if (client.Matches(addr)) { return client; } } - clients.emplace_back(addr); - OnConnect(clients.back()); + clients.emplace_back(*this, addr); return clients.back(); } -void Server::OnConnect(Connection &client) { - cout << "new connection from " << client.Address() << endl; - // tell it we're alive - client.SendPing(serv_pack, serv_sock); -} - void Server::Update(int dt) { - for (list::iterator client(clients.begin()), end(clients.end()); client != end;) { + for (list::iterator client(clients.begin()), end(clients.end()); client != end;) { client->Update(dt); - if (client->Closed()) { - OnDisconnect(*client); + if (client->Disconnected()) { client = clients.erase(client); } else { - if (client->ShouldPing()) { - client->SendPing(serv_pack, serv_sock); - } ++client; } } } -void Server::OnDisconnect(Connection &client) { - cout << "connection timeout from " << client.Address() << endl; -} - - -void Server::HandleLogin(Connection &client, const UDPpacket &udp_pack) { - auto pack = Packet::As(udp_pack); - - string name; - pack.ReadPlayerName(name); - - Entity *player = world.AddPlayer(name); - - if (player) { - // success! - cout << "accepted login from player \"" << name << '"' << endl; - auto response = Packet::Make(serv_pack); - response.WritePlayer(*player); - response.WriteWorldName(world.Name()); - client.Send(serv_pack, serv_sock); - } else { - // aw no :( - cout << "rejected login from player \"" << name << '"' << endl; - Packet::Make(serv_pack); - client.Send(serv_pack, serv_sock); - client.Close(); - } -} - -void Server::HandlePart(Connection &client, const UDPpacket &udp_pack) { - client.Close(); -} - }