]> git.tdb.fi Git - libs/game.git/commitdiff
Add interfaces for using Networking from the outside
authorMikko Rasa <tdb@tdb.fi>
Sun, 11 Jun 2023 14:55:31 +0000 (17:55 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 11 Jun 2023 17:16:56 +0000 (20:16 +0300)
source/game/networking.cpp
source/game/networking.h
source/game/protocol.cpp
source/game/protocol.h

index ad516327b2e38a02a0d6be9f991cb1c806ab62a6..9c2894f8c8d271a5da20c170db38eaa3526e3fe4 100644 (file)
@@ -83,6 +83,28 @@ void Networking::reap_connections()
        }
 }
 
+unsigned Networking::get_next_protocol_id()
+{
+       static unsigned next_id = 0;
+       return next_id++;
+}
+
+void Networking::set_protocol(unsigned id, unique_ptr<Net::Protocol> net_proto)
+{
+       if(protocols.size()<=id)
+               protocols.resize(id+1);
+
+       Protocol &proto = protocols[id];
+       proto.protocol = move(net_proto);
+       if(state==SERVER)
+       {
+               for(const auto &c: clients)
+                       c->get_communicator().add_protocol(*proto.protocol, proto.receiver);
+       }
+       else if(state==CONNECTING || state==CONNECTED)
+               connection->get_communicator().add_protocol(*proto.protocol, proto.receiver);
+}
+
 uint16_t Networking::intern_string(const string &value)
 {
        auto i = find(strings, value);
@@ -160,7 +182,7 @@ void Networking::set_state(State s)
 
 void Networking::protocol_ready(const Net::Protocol &p)
 {
-       if(state==CONNECTING && &p==&protocol)
+       if(state==CONNECTING && &p==&core_protocol)
                set_state(CONNECTED);
 }
 
@@ -212,7 +234,7 @@ void Networking::Connection::error(const exception &)
 Networking::ServerConnection::ServerConnection(Networking &n, const Net::SockAddr &addr):
        Connection(n, make_unique<Net::StreamSocket>(addr.get_family()))
 {
-       communicator.add_protocol(networking.protocol, *this);
+       communicator.add_protocol(networking.core_protocol, *this);
        socket->set_block(false);
        socket->signal_connect_finished.connect(sigc::mem_fun(this, &ServerConnection::connect_finished));
        socket->connect(addr);
@@ -275,12 +297,14 @@ Networking::ClientConnection::ClientConnection(Networking &n, unique_ptr<Net::St
        Connection(n, move(s))
 {
        communicator.signal_protocol_ready.connect(sigc::mem_fun(this, &ClientConnection::protocol_ready));
-       communicator.add_protocol(networking.protocol, *this);
+       communicator.add_protocol(networking.core_protocol, *this);
+       for(Protocol &p: networking.protocols)
+               communicator.add_protocol(*p.protocol, p.receiver);
 }
 
 void Networking::ClientConnection::protocol_ready(const Net::Protocol &p)
 {
-       if(&p==&networking.protocol)
+       if(&p==&networking.core_protocol)
        {
                size_t n_strings = networking.strings.size();
                for(size_t i=1; i<n_strings; ++i)
index 52a01c3337481dc7f5a1a7fd7159ca7edb346a4c..c12f39f2dbb5172aae4f79a6117939814d469b30 100644 (file)
@@ -30,6 +30,22 @@ public:
                Events::NetworkPlayerDeparted, Events::ServerStageActivated>;
 
 private:
+       class SwitchableReceiver: public Net::DynamicReceiver
+       {
+       private:
+               Net::DynamicReceiver *receiver = nullptr;
+
+       public:
+               void set_receiver(Net::DynamicReceiver *r) { receiver = r; }
+               void receive(unsigned i, const Variant &p) override { if(receiver) receiver->receive(i, p); }
+       };
+
+       struct Protocol
+       {
+               std::unique_ptr<Net::Protocol> protocol;
+               SwitchableReceiver receiver;
+       };
+
        class Connection
        {
        protected:
@@ -98,8 +114,9 @@ private:
        EventSource event_source;
        EventObserver observer;
        IO::EventDispatcher &io_disp;
-       Protocol protocol;
        State state = DISABLED;
+       CoreProtocol core_protocol;
+       std::vector<Protocol> protocols;
        std::unique_ptr<Net::StreamServerSocket> server_socket;
        std::unique_ptr<ServerConnection> connection;
        std::vector<std::unique_ptr<ClientConnection>> clients;
@@ -117,6 +134,15 @@ public:
        void disable();
        void reap_connections();
 
+       template<typename P>
+       const Net::Protocol &set_receiver(Net::DynamicReceiver *);
+
+private:
+       static unsigned get_next_protocol_id();
+
+       void set_protocol(unsigned, std::unique_ptr<Net::Protocol>);
+
+public:
        std::uint16_t intern_string(const std::string &);
        const std::string &get_string(std::uint16_t) const;
 
@@ -124,6 +150,14 @@ public:
 private:
        Player &create_player(const std::string &, unsigned = 0);
 
+public:
+       template<typename P>
+       void send(const P &);
+
+       template<typename P>
+       void send(unsigned, const P &);
+
+private:
        void set_state(State);
        void protocol_ready(const Net::Protocol &);
        void incoming_connection();
@@ -132,6 +166,45 @@ private:
 };
 
 
+template<typename P>
+const Net::Protocol &Networking::set_receiver(Net::DynamicReceiver *r)
+{
+       static unsigned id = get_next_protocol_id();
+       if(id>=protocols.size() || !protocols[id].protocol)
+               set_protocol(id, std::make_unique<P>());
+
+       protocols[id].receiver.set_receiver(r);
+       return *protocols[id].protocol.get();
+}
+
+template<typename P>
+void Networking::send(const P &packet)
+{
+       if(state==SERVER)
+       {
+               for(const auto &c: clients)
+                       c->get_communicator().send(packet);
+       }
+       else if(state==CONNECTED)
+               connection->get_communicator().send(packet);
+       else
+               throw invalid_state("Networking::send");
+}
+
+template<typename P>
+void Networking::send(unsigned target, const P &packet)
+{
+       if(state!=SERVER)
+               throw invalid_state("Networking::send");
+
+       auto i = lower_bound_member(players, target, &Player::id);
+       if(i==players.end() || i->id!=target)
+               throw key_error(i);
+
+       i->owner->get_communicator().send(packet);
+}
+
+
 namespace Events {
 
 struct NetworkStateChanged
index dfa8f29a691b977555d6d977d201ce9537dee52b..9eddbb7f791d80191c9aa9ccb0858e0977558607 100644 (file)
@@ -3,7 +3,7 @@
 
 namespace Msp::Game {
 
-Protocol::Protocol()
+CoreProtocol::CoreProtocol()
 {
        using namespace Messages;
 
index efeca1f541996de0cd5a7c60e01d067f81147e75..0749693ea1c51d9ff98300d2a140685c728ef6c6 100644 (file)
@@ -5,10 +5,10 @@
 
 namespace Msp::Game {
 
-class Protocol: public Net::Protocol
+class CoreProtocol: public Net::Protocol
 {
 public:
-       Protocol();
+       CoreProtocol();
 };
 
 } // namespace Msp::Game