]> git.localhorst.tv Git - blank.git/commitdiff
defined and implemented join and part packets
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 3 Sep 2015 08:39:52 +0000 (10:39 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 3 Sep 2015 08:40:21 +0000 (10:40 +0200)
doc/protocol
src/app/Runtime.hpp
src/app/runtime.cpp
src/net/Connection.hpp
src/net/Packet.hpp
src/net/Server.hpp
src/net/net.cpp
src/world/World.hpp

index 723f3cfbd38586283fb24ca310f5858e60593bd4..63055a267fce123b022ef54ba6fdfad26ef649c4 100644 (file)
@@ -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
index ee438537a345ef43e0f884f24ca799588b15ba4a..904431b021bf2d346fac78e9dff5d2586ea05414 100644 (file)
@@ -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();
index 2d128631a2e19d8bde4af93c022cee5da248e798..e551e9d9309811f539f36d65800560ade736e8fd 100644 (file)
@@ -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 {
index ade65ebd4d955939ead5a4840409c5d5bbb5db58..cc13ef60915df48dc676228535c50101f0eccc9d 100644 (file)
@@ -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;
+
 };
 
 }
index b7c8a5fa5aeb90d3b018cd2d791a771ff687f041..0d99fee2992c74c61a1979dfe251813c69e607ca 100644 (file)
@@ -2,11 +2,14 @@
 #define BLANK_NET_PACKET_HPP_
 
 #include <cstdint>
+#include <ostream>
 #include <string>
 
 
 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
index 6a1e9969bea693cbead97fafb5b9ec73d0cb7348..a95cd37bea9aa41c119783538e44e08af423d840 100644 (file)
@@ -34,6 +34,7 @@ private:
        void OnDisconnect(Connection &);
 
        void HandleLogin(Connection &client, const UDPpacket &);
+       void HandlePart(Connection &client, const UDPpacket &);
 
 private:
        UDPsocket serv_sock;
index 314410ebbdb66fee6bb053f43a7dac6d02762dd6..9c29c1e09edeb96d9c7de52d433ad4e2f15ec341 100644 (file)
@@ -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<Packet *>(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<Packet *>(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<Packet *>(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<Packet *>(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<uint32_t *>(cursor) = 1;
+       cursor += 4;
+
+       *reinterpret_cast<glm::ivec3 *>(cursor) = player.ChunkCoords();
+       cursor += 12;
+
+       *reinterpret_cast<glm::vec3 *>(cursor) = player.Position();
+       cursor += 12;
+       *reinterpret_cast<glm::vec3 *>(cursor) = player.Velocity();
+       cursor += 12;
+
+       *reinterpret_cast<glm::quat *>(cursor) = player.Orientation();
+       cursor += 16;
+       *reinterpret_cast<glm::vec3 *>(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<Connection>::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<Packet *>(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();
+}
+
 }
index 3981b28e336f9dcf8e28ee84411486d1e23121d2..7d2c2926a1732ee4ea5f663cd112f3de6dd4335a 100644 (file)
@@ -6,6 +6,7 @@
 #include "Generator.hpp"
 
 #include <list>
+#include <string>
 #include <vector>
 #include <glm/glm.hpp>
 
@@ -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