From da5073a7fdb1ca066e778a02db33d5d15073aea0 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Thu, 3 Sep 2015 10:39:52 +0200 Subject: [PATCH] defined and implemented join and part packets --- doc/protocol | 30 +++++++++++- src/app/Runtime.hpp | 1 - src/app/runtime.cpp | 8 ++-- src/net/Connection.hpp | 5 ++ src/net/Packet.hpp | 19 +++++++- src/net/Server.hpp | 1 + src/net/net.cpp | 101 +++++++++++++++++++++++++++++++++++------ src/world/World.hpp | 4 ++ 8 files changed, 145 insertions(+), 24 deletions(-) diff --git a/doc/protocol b/doc/protocol index 723f3cf..63055a2 100644 --- a/doc/protocol +++ b/doc/protocol @@ -21,5 +21,31 @@ been reached. Code: 1 Payload: - player name, max 32 byte UTF-8 string, - shorter names should be zero terminated + 0 player name, max 32 byte UTF-8 string, + shorter names should be zero terminated + + +Join +---- + +Sent by the server either as a response to a successful login or when +it's changing worlds. + +Code: 2 +Payload: + 0 entity ID of the player, 32bit unsigned int + 4 chunk coords of the player, 3x 32bit signed int + 16 pos/vel/rot/ang of the player, 13x 32bit float + 68 name of the world the server's currently running + max 32 byte UTF-8 string + + +Part +---- + +Sent by the server either as a respons to a failed login or when the +client was kicked. +Optionally sent by the client on disconnect. + +Code: 3 +Payload: none diff --git a/src/app/Runtime.hpp b/src/app/Runtime.hpp index ee43853..904431b 100644 --- a/src/app/Runtime.hpp +++ b/src/app/Runtime.hpp @@ -44,7 +44,6 @@ public: std::string asset_path; std::string save_path; - std::string world_name = "default"; Client::Config client = Client::Config(); Interface::Config interface = Interface::Config(); diff --git a/src/app/runtime.cpp b/src/app/runtime.cpp index 2d12863..e551e9d 100644 --- a/src/app/runtime.cpp +++ b/src/app/runtime.cpp @@ -164,7 +164,7 @@ void Runtime::ReadArgs(int argc, const char *const *argv) { cerr << "missing argument to --world-name" << endl; error = true; } else { - config.world_name = argv[i]; + config.world.name = argv[i]; } } else { cerr << "unknown option " << arg << endl; @@ -296,7 +296,7 @@ void Runtime::RunStandalone() { Environment env(init.window, config.asset_path); env.viewport.VSync(config.vsync); - WorldSave save(config.save_path + config.world_name + '/'); + WorldSave save(config.save_path + config.world.name + '/'); if (save.Exists()) { save.Read(config.world); } else { @@ -321,7 +321,7 @@ void Runtime::RunStandalone() { void Runtime::RunServer() { HeadlessEnvironment env(config.asset_path); - WorldSave save(config.save_path + config.world_name + '/'); + WorldSave save(config.save_path + config.world.name + '/'); if (save.Exists()) { save.Read(config.world); } else { @@ -340,7 +340,7 @@ void Runtime::RunClient() { Environment env(init.window, config.asset_path); env.viewport.VSync(config.vsync); - WorldSave save(config.save_path + config.world_name + '/'); + WorldSave save(config.save_path + config.world.name + '/'); if (save.Exists()) { save.Read(config.world); } else { diff --git a/src/net/Connection.hpp b/src/net/Connection.hpp index ade65eb..cc13ef6 100644 --- a/src/net/Connection.hpp +++ b/src/net/Connection.hpp @@ -22,6 +22,9 @@ public: bool ShouldPing() const noexcept; bool TimedOut() const noexcept; + void Close() noexcept { closed = true; } + bool Closed() const noexcept { return closed || TimedOut(); } + void Update(int dt); void SendPing(UDPpacket &, UDPsocket); @@ -40,6 +43,8 @@ private: Packet::TControl ctrl; + bool closed; + }; } diff --git a/src/net/Packet.hpp b/src/net/Packet.hpp index b7c8a5f..0d99fee 100644 --- a/src/net/Packet.hpp +++ b/src/net/Packet.hpp @@ -2,11 +2,14 @@ #define BLANK_NET_PACKET_HPP_ #include +#include #include namespace blank { +class Entity; + struct Packet { static constexpr std::uint32_t TAG = 0xFB1AB1AF; @@ -14,8 +17,12 @@ struct Packet { enum Type { PING = 0, LOGIN = 1, + JOIN = 2, + PART = 3, }; + static const char *Type2String(Type) noexcept; + struct TControl { std::uint16_t seq; std::uint16_t ack; @@ -31,13 +38,21 @@ struct Packet { std::uint8_t payload[500 - sizeof(Header)]; + Type GetType() const noexcept { return Type(header.type); } + void Tag() noexcept; - std::size_t Ping() noexcept; - std::size_t Login(const std::string &name) noexcept; + std::size_t MakePing() noexcept; + std::size_t MakeLogin(const std::string &name) noexcept; + std::size_t MakeJoin(const Entity &player, const std::string &world_name) noexcept; + std::size_t MakePart() noexcept; }; +inline std::ostream &operator <<(std::ostream &out, Packet::Type t) { + return out << Packet::Type2String(t); +} + } #endif diff --git a/src/net/Server.hpp b/src/net/Server.hpp index 6a1e996..a95cd37 100644 --- a/src/net/Server.hpp +++ b/src/net/Server.hpp @@ -34,6 +34,7 @@ private: void OnDisconnect(Connection &); void HandleLogin(Connection &client, const UDPpacket &); + void HandlePart(Connection &client, const UDPpacket &); private: UDPsocket serv_sock; diff --git a/src/net/net.cpp b/src/net/net.cpp index 314410e..9c29c1e 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -76,7 +76,6 @@ void Client::HandlePacket(const UDPpacket &udp_pack) { } conn.Received(udp_pack); - cout << "I got something!" << endl; } void Client::Update(int dt) { @@ -94,16 +93,17 @@ void Client::SendPing() { void Client::SendLogin(const string &name) { Packet &pack = *reinterpret_cast(client_pack.data); - client_pack.len = pack.Login(name); + client_pack.len = pack.MakeLogin(name); conn.Send(client_pack, client_sock); } Connection::Connection(const IPaddress &addr) : addr(addr) -, send_timer(5000) +, send_timer(3000) , recv_timer(10000) -, ctrl{ 0, 0xFFFF, 0xFFFF } { +, ctrl{ 0, 0xFFFF, 0xFFFF } +, closed(false) { send_timer.Start(); recv_timer.Start(); } @@ -138,6 +138,8 @@ void Connection::Send(UDPpacket &udp_pack, UDPsocket sock) { Packet &pack = *reinterpret_cast(udp_pack.data); pack.header.ctrl = ctrl; + cout << "sending " << pack.GetType() << " to " << Address() << endl; + udp_pack.address = addr; if (SDLNet_UDP_Send(sock, -1, &udp_pack) == 0) { throw NetError("SDLNet_UDP_Send"); @@ -149,6 +151,8 @@ void Connection::Send(UDPpacket &udp_pack, UDPsocket sock) { void Connection::Received(const UDPpacket &udp_pack) { Packet &pack = *reinterpret_cast(udp_pack.data); + cout << "received " << pack.GetType() << " from " << Address() << endl; + int diff = std::int16_t(pack.header.ctrl.seq) - std::int16_t(ctrl.ack); if (diff > 0) { @@ -183,7 +187,7 @@ void Connection::Received(const UDPpacket &udp_pack) { void Connection::SendPing(UDPpacket &udp_pack, UDPsocket sock) { Packet &pack = *reinterpret_cast(udp_pack.data); - udp_pack.len = pack.Ping(); + udp_pack.len = pack.MakePing(); Send(udp_pack, sock); } @@ -201,17 +205,32 @@ ostream &operator <<(ostream &out, const IPaddress &addr) { } +const char *Packet::Type2String(Type t) noexcept { + switch (t) { + case PING: + return "PING"; + case LOGIN: + return "LOGIN"; + case JOIN: + return "JOIN"; + case PART: + return "PART"; + default: + return "UNKNOWN"; + } +} + void Packet::Tag() noexcept { header.tag = TAG; } -size_t Packet::Ping() noexcept { +size_t Packet::MakePing() noexcept { Tag(); header.type = PING; return sizeof(Header); } -size_t Packet::Login(const string &name) noexcept { +size_t Packet::MakeLogin(const string &name) noexcept { constexpr size_t maxname = 32; Tag(); @@ -225,6 +244,48 @@ size_t Packet::Login(const string &name) noexcept { return sizeof(Header) + maxname; } +size_t Packet::MakeJoin(const Entity &player, const string &world_name) noexcept { + constexpr size_t maxname = 32; + + Tag(); + header.type = JOIN; + + uint8_t *cursor = &payload[0]; + + // TODO: generate entity IDs + *reinterpret_cast(cursor) = 1; + cursor += 4; + + *reinterpret_cast(cursor) = player.ChunkCoords(); + cursor += 12; + + *reinterpret_cast(cursor) = player.Position(); + cursor += 12; + *reinterpret_cast(cursor) = player.Velocity(); + cursor += 12; + + *reinterpret_cast(cursor) = player.Orientation(); + cursor += 16; + *reinterpret_cast(cursor) = player.AngularVelocity(); + cursor += 12; + + if (world_name.size() < maxname) { + memset(cursor, '\0', maxname); + memcpy(cursor, world_name.c_str(), world_name.size()); + } else { + memcpy(cursor, world_name.c_str(), maxname); + } + cursor += maxname; + + return sizeof(Header) + (cursor - &payload[0]); +} + +size_t Packet::MakePart() noexcept { + Tag(); + header.type = PART; + return sizeof(Header); +} + Server::Server(const Config &conf, World &world) : serv_sock(nullptr) @@ -273,14 +334,14 @@ void Server::HandlePacket(const UDPpacket &udp_pack) { client.Received(udp_pack); switch (pack.header.type) { - case Packet::PING: - // already done all that's supposed to do - break; case Packet::LOGIN: HandleLogin(client, udp_pack); break; + case Packet::PART: + HandlePart(client, udp_pack); + break; default: - // just drop packets of unknown type + // just drop packets of unknown or unhandled type break; } } @@ -305,7 +366,7 @@ void Server::OnConnect(Connection &client) { void Server::Update(int dt) { for (list::iterator client(clients.begin()), end(clients.end()); client != end;) { client->Update(dt); - if (client->TimedOut()) { + if (client->Closed()) { OnDisconnect(*client); client = clients.erase(client); } else { @@ -330,16 +391,26 @@ void Server::HandleLogin(Connection &client, const UDPpacket &udp_pack) { for (size_t i = 0; i < maxlen && pack.payload[i] != '\0'; ++i) { name.push_back(pack.payload[i]); } - cout << "got login request from player \"" << name << '"' << endl; Entity *player = world.AddPlayer(name); + Packet &response = *reinterpret_cast(serv_pack.data); + if (player) { // success! - cout << "\taccepted" << endl; + cout << "accepted login from player \"" << name << '"' << endl; + response.MakeJoin(*player, world.Name()); + client.Send(serv_pack, serv_sock); } else { // aw no :( - cout << "\trejected" << endl; + cout << "rejected login from player \"" << name << '"' << endl; + response.MakePart(); + client.Send(serv_pack, serv_sock); + client.Close(); } } +void Server::HandlePart(Connection &client, const UDPpacket &udp_pack) { + client.Close(); +} + } diff --git a/src/world/World.hpp b/src/world/World.hpp index 3981b28..7d2c292 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -6,6 +6,7 @@ #include "Generator.hpp" #include +#include #include #include @@ -21,6 +22,7 @@ class World { public: struct Config { + std::string name = "default"; // initial player position glm::vec3 spawn = { 0.0f, 0.0f, 0.0f }; // direction facing towards(!) the light @@ -37,6 +39,8 @@ public: World(const BlockTypeRegistry &, const Config &, const WorldSave &); + const std::string &Name() const noexcept { return config.name; } + /// check if this ray hits a block /// depth in the collision is the distance between the ray's /// origin and the intersection point -- 2.39.2