]> git.tdb.fi Git - libs/game.git/commitdiff
Add more kinds of remote calls
authorMikko Rasa <tdb@tdb.fi>
Thu, 11 Jan 2024 21:53:34 +0000 (23:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 11 Jan 2024 21:53:34 +0000 (23:53 +0200)
source/game/remotecall.h

index 35cfe88ac8035562e421fa8453f7a317d5d479f2..e5e0fb768979f8fe6d3afff405c4be88a0d26aab 100644 (file)
 
 namespace Msp::Game {
 
-template<typename P>
-class ReplicatedCall: private Net::PacketReceiver<P>
+template<typename P, typename F = void(const P &)>
+class RemoteCallBase: protected Net::PacketReceiver<P>
 {
-public:
-       using Function = std::function<void(const P &)>;
+protected:
+       using Function = std::function<F>;
 
-private:
-       Replicator *replicator = nullptr;
+       Replicator *replicator;
        Function func;
 
+       RemoteCallBase(Replicator *, Function);
+};
+
+
+template<typename P, typename E = Entity>
+       requires std::is_base_of_v<Entity, E>
+class RemoteEntityCallBase: protected RemoteCallBase<P, void(Handle<E>, const P &)>
+{
+protected:
+       using RemoteCallBase<P, void(Handle<E>, const P &)>::RemoteCallBase;
+
+       void prepare(Handle<E>, P &);
+       void call(const P &);
+};
+
+
+template<typename P>
+class ReplicatedCall: public RemoteCallBase<P>
+{
 public:
-       ReplicatedCall(Replicator *, Function);
+       ReplicatedCall(Replicator *r, RemoteCallBase<P>::Function f): RemoteCallBase<P>(r, std::move(f)) { }
 
        void operator()(P &);
        void operator()(unsigned, P &);
 
 private:
-       void receive(const P &) override;
+       void receive(const P &p) override { this->func(p); }
 };
 
 
-template<typename P, typename E = Entity>
-       requires std::is_base_of_v<Entity, E>
-class ReplicatedEntityCall: private Net::PacketReceiver<P>
+template<typename P>
+class RequestCall: public RemoteCallBase<P>
 {
 public:
-       using Function = std::function<void(Handle<E>, const P &)>;
+       RequestCall(Replicator *, RemoteCallBase<P>::Function);
+
+       void operator()(P &);
 
 private:
-       Replicator *replicator = nullptr;
-       Function func;
+       void receive(const P &p) override { this->func(p); }
+};
 
+
+template<typename P, typename E = Entity>
+class ReplicatedEntityCall: public RemoteEntityCallBase<P, E>
+{
 public:
-       ReplicatedEntityCall(Replicator *, Function);
+       ReplicatedEntityCall(Replicator *r, RemoteEntityCallBase<P, E>::Function f): RemoteEntityCallBase<P, E>(r, std::move(f)) { }
 
-       void operator()(Handle<Entity>, P &);
-       void operator()(unsigned, Handle<Entity>, P &);
+       void operator()(Handle<E>, P &);
+       void operator()(unsigned, Handle<E>, P &);
+
+       void receive(const P &p) override { this->call(p); }
+};
 
-private:
-       void prepare(Handle<Entity>, P &);
 
+template<typename P, typename E = Entity>
+class EntityRequestCall: public RemoteEntityCallBase<P, E>
+{
 public:
-       void receive(const P &) override;
+       EntityRequestCall(Replicator *r, RemoteEntityCallBase<P, E>::Function f): RemoteEntityCallBase<P, E>(r, std::move(f)) { }
+
+       void operator()(Handle<E>, P &);
+
+       void receive(const P &p) override { this->call(p); }
 };
 
 
-template<typename P>
-ReplicatedCall<P>::ReplicatedCall(Replicator *r, std::function<void(const P &)> f):
+template<typename P, typename F>
+RemoteCallBase<P, F>::RemoteCallBase(Replicator *r, Function f):
        replicator(r),
        func(std::move(f))
 {
@@ -65,82 +96,97 @@ ReplicatedCall<P>::ReplicatedCall(Replicator *r, std::function<void(const P &)>
                replicator->add_receiver<P>(*this);
 }
 
+
+template<typename P, typename E>
+       requires std::is_base_of_v<Entity, E>
+void RemoteEntityCallBase<P, E>::prepare(Handle<E> entity, P &packet)
+{
+       Handle<Zygote> zygote = entity->template get_component<Zygote>();
+       if(!zygote)
+               throw std::invalid_argument("ReplicatedEntityCall::operator()");
+
+       std::uint32_t entity_id = zygote->get_entity_id();
+       if(entity_id==Zygote::NO_ID)
+               throw std::invalid_argument("ReplicatedEntityCall::operator()");
+
+       packet.entity_id = entity_id;
+}
+
+template<typename P, typename E>
+       requires std::is_base_of_v<Entity, E>
+void RemoteEntityCallBase<P, E>::call(const P &packet)
+{
+       Handle<Entity> entity = this->replicator->find_entity(packet.entity_id);
+       if(!entity)
+               return;  // TODO report the error somehow
+
+       Handle<E> cast_entity = dynamic_handle_cast<E>(entity);
+       if(!cast_entity)
+               return;
+
+       this->func(cast_entity, packet);
+}
+
+
 template<typename P>
 void ReplicatedCall<P>::operator()(P &packet)
 {
-       if(replicator)
-               replicator->send(packet);
+       if(this->replicator)
+               this->replicator->send(packet);
        func(packet);
 }
 
+
 template<typename P>
-void ReplicatedCall<P>::receive(const P &packet)
+void ReplicatedCall<P>::operator()(unsigned target, P &packet)
 {
-       func(packet);
+       if(this->replicator)
+               this->replicator->send(target, packet);
 }
 
 
-template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E>
-ReplicatedEntityCall<P, E>::ReplicatedEntityCall(Replicator *r, Function f):
-       replicator(r),
-       func(std::move(f))
+template<typename P>
+void RequestCall<P>::operator()(P &packet)
 {
-       if(replicator)
-               replicator->add_receiver<P>(*this);
+       if(this->replicator && !this->replicator->is_server())
+               this->replicator->send(packet);
+       else
+               this->func(packet);
 }
 
+
 template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E>
-void ReplicatedEntityCall<P, E>::operator()(Handle<Entity> entity, P &packet)
+void ReplicatedEntityCall<P, E>::operator()(Handle<E> entity, P &packet)
 {
-       if(replicator)
+       if(this->replicator)
        {
-               prepare(entity, packet);
-               replicator->send(entity, packet);
+               this->prepare(entity, packet);
+               this->replicator->send(entity, packet);
        }
-       func(entity, packet);
+       this->func(entity, packet);
 }
 
 template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E>
-void ReplicatedEntityCall<P, E>::operator()(unsigned target, Handle<Entity> entity, P &packet)
+void ReplicatedEntityCall<P, E>::operator()(unsigned target, Handle<E> entity, P &packet)
 {
-       if(replicator)
+       if(this->replicator)
        {
-               prepare(entity, packet);
-               replicator->send(target, packet);
+               this->prepare(entity, packet);
+               this->replicator->send(target, packet);
        }
 }
 
-template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E>
-void ReplicatedEntityCall<P, E>::prepare(Handle<Entity> entity, P &packet)
-{
-       Handle<Zygote> zygote = entity->get_component<Zygote>();
-       if(!zygote)
-               throw std::invalid_argument("ReplicatedEntityCall::operator()");
-
-       std::uint32_t entity_id = zygote->get_entity_id();
-       if(entity_id==Zygote::NO_ID)
-               throw std::invalid_argument("ReplicatedEntityCall::operator()");
-
-       packet.entity_id = entity_id;
-}
 
 template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E>
-void ReplicatedEntityCall<P, E>::receive(const P &packet)
+void EntityRequestCall<P, E>::operator()(Handle<E> entity, P &packet)
 {
-       Handle<Entity> entity = replicator->find_entity(packet.entity_id);
-       if(!entity)
-               return;  // TODO report the error somehow
-
-       Handle<E> cast_entity = dynamic_handle_cast<E>(entity);
-       if(!cast_entity)
-               return;
-
-       func(cast_entity, packet);
+       if(this->replicator && !this->replicator->is_server())
+       {
+               this->prepare(entity, packet);
+               this->replicator->send(entity, packet);
+       }
+       else
+               this->func(entity, packet);
 }
 
 } // namespace Msp::Game