From: Mikko Rasa Date: Sun, 11 Jun 2023 14:55:31 +0000 (+0300) Subject: Add interfaces for using Networking from the outside X-Git-Url: https://git.tdb.fi/?a=commitdiff_plain;h=78ea89f44afeb0386d9d2fd164cd46dc456872ba;p=libs%2Fgame.git Add interfaces for using Networking from the outside --- diff --git a/source/game/networking.cpp b/source/game/networking.cpp index ad51632..9c2894f 100644 --- a/source/game/networking.cpp +++ b/source/game/networking.cpp @@ -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_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(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; 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 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 protocols; std::unique_ptr server_socket; std::unique_ptr connection; std::vector> clients; @@ -117,6 +134,15 @@ public: void disable(); void reap_connections(); + template + const Net::Protocol &set_receiver(Net::DynamicReceiver *); + +private: + static unsigned get_next_protocol_id(); + + void set_protocol(unsigned, std::unique_ptr); + +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 + void send(const P &); + + template + 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 +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

()); + + protocols[id].receiver.set_receiver(r); + return *protocols[id].protocol.get(); +} + +template +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 +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 diff --git a/source/game/protocol.cpp b/source/game/protocol.cpp index dfa8f29..9eddbb7 100644 --- a/source/game/protocol.cpp +++ b/source/game/protocol.cpp @@ -3,7 +3,7 @@ namespace Msp::Game { -Protocol::Protocol() +CoreProtocol::CoreProtocol() { using namespace Messages; diff --git a/source/game/protocol.h b/source/game/protocol.h index efeca1f..0749693 100644 --- a/source/game/protocol.h +++ b/source/game/protocol.h @@ -5,10 +5,10 @@ namespace Msp::Game { -class Protocol: public Net::Protocol +class CoreProtocol: public Net::Protocol { public: - Protocol(); + CoreProtocol(); }; } // namespace Msp::Game