]> git.tdb.fi Git - libs/game.git/commitdiff
Consolidate the remote call classes
authorMikko Rasa <tdb@tdb.fi>
Sun, 21 Jan 2024 17:47:16 +0000 (19:47 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 21 Jan 2024 17:47:16 +0000 (19:47 +0200)
Global and entity calls are now declared using the same class.  If the
entity type is void (the default), the call is global.

source/game/landscape.h
source/game/remotecall.h

index aa042e5ee50b51313f9ebc6301f60e4c4f3bbe73..8463b1434e273363b89c021d8d94efba6a4a6eda 100644 (file)
@@ -52,7 +52,7 @@ private:
        };
 
        Replicator *replicator = nullptr;
-       ReplicatedEntityCall<Messages::LandscapeData, TerrainBlock> data_call;
+       ReplicatedCall<Messages::LandscapeData, TerrainBlock> data_call;
        Owned<Entity> subroot;
        Spawner spawner;
        BlockSetup block_setup;
index 8b830c43b4e57b99fd4376c937203fb5f6fae4fc..a78f6126f37601cf97af6a11ac695fc7793574cd 100644 (file)
@@ -4,8 +4,10 @@
 #include <concepts>
 #include <functional>
 #include <stdexcept>
+#include <typeinfo>
 #include <msp/net/receiver.h>
 #include "entity.h"
+#include "mspgame_api.h"
 #include "replicator.h"
 #include "zygote.h"
 
@@ -14,178 +16,160 @@ namespace Msp::Game {
 template<typename P>
 concept HasEntityIdField = requires(P p) { { (p.entity_id) } -> std::same_as<std::uint32_t &>; };
 
-template<typename P, typename F = void(const P &)>
-class RemoteCallBase: protected Net::PacketReceiver<P>
+template<typename P, typename E>
+concept ValidRemoteCall = std::is_same_v<E, void> || (std::is_base_of_v<Entity, E> && HasEntityIdField<P>);
+
+
+template<typename P, typename E>
+       requires ValidRemoteCall<P, E>
+class RemoteCall: protected Net::PacketReceiver<P>
 {
 protected:
-       using Function = std::function<F>;
+       using Function = std::conditional_t<std::is_same_v<E, void>,
+               std::function<void(const P &)>, std::function<void(Handle<E>, const P &)>>;
 
-       Replicator *replicator;
+       Replicator *replicator = nullptr;
        Function func;
 
-       RemoteCallBase(Replicator *, Function);
-};
-
-
-template<typename P, typename E = Entity>
-       requires std::is_base_of_v<Entity, E> && HasEntityIdField<P>
-class RemoteEntityCallBase: protected RemoteCallBase<P, void(Handle<E>, const P &)>
-{
-protected:
-       using RemoteCallBase<P, void(Handle<E>, const P &)>::RemoteCallBase;
+       RemoteCall(Replicator *, Function);
 
-       void prepare(Handle<E>, P &);
-       void call(const P &);
+       void prepare(Handle<E>, P &) const;
+       void receive(P &&) override;
 };
 
 
-template<typename P>
-class ReplicatedCall: public RemoteCallBase<P>
+template<typename P, typename E = void>
+class ReplicatedCall: public RemoteCall<P, E>
 {
 public:
-       ReplicatedCall(Replicator *r, RemoteCallBase<P>::Function f): RemoteCallBase<P>(r, std::move(f)) { }
-
-       void operator()(P &);
-       void operator()(unsigned, P &);
+       ReplicatedCall(Replicator *r, RemoteCall<P, E>::Function f): RemoteCall<P, E>(r, std::move(f)) { }
 
-private:
-       void receive(P &&p) override { this->func(p); }
+       void operator()(Handle<E>, P &);
+       void operator()(unsigned, Handle<E>, P &);
 };
 
-
 template<typename P>
-class RequestCall: public RemoteCallBase<P>
+class ReplicatedCall<P, void>: public RemoteCall<P, void>
 {
 public:
-       RequestCall(Replicator *, RemoteCallBase<P>::Function);
-
-       void operator()(P &);
+       ReplicatedCall(Replicator *r, RemoteCall<P, void>::Function f): RemoteCall<P, void>(r, std::move(f)) { }
 
-private:
-       void receive(P &&p) override { this->func(p); }
+       void operator()(const P &);
+       void operator()(unsigned, const P &);
 };
 
 
-template<typename P, typename E = Entity>
-class ReplicatedEntityCall: public RemoteEntityCallBase<P, E>
+template<typename P, typename E = void>
+class RequestCall: public RemoteCall<P, E>
 {
 public:
-       ReplicatedEntityCall(Replicator *r, RemoteEntityCallBase<P, E>::Function f): RemoteEntityCallBase<P, E>(r, std::move(f)) { }
+       RequestCall(Replicator *r, RemoteCall<P, E>::Function f): RemoteCall<P, E>(r, std::move(f)) { }
 
        void operator()(Handle<E>, P &);
-       void operator()(unsigned, Handle<E>, P &);
-
-       void receive(P &&p) override { this->call(p); }
 };
 
-
-template<typename P, typename E = Entity>
-class EntityRequestCall: public RemoteEntityCallBase<P, E>
+template<typename P>
+class RequestCall<P, void>: public RemoteCall<P, void>
 {
 public:
-       EntityRequestCall(Replicator *r, RemoteEntityCallBase<P, E>::Function f): RemoteEntityCallBase<P, E>(r, std::move(f)) { }
-
-       void operator()(Handle<E>, P &);
+       RequestCall(Replicator *r, RemoteCall<P, void>::Function f): RemoteCall<P, void>(r, std::move(f)) { }
 
-       void receive(P &&p) override { this->call(p); }
+       void operator()(P &);
 };
 
 
-template<typename P, typename F>
-RemoteCallBase<P, F>::RemoteCallBase(Replicator *r, Function f):
+template<typename P, typename E>
+       requires ValidRemoteCall<P, E>
+RemoteCall<P, E>::RemoteCall(Replicator *r, Function f):
        replicator(r),
        func(std::move(f))
 {
        if(replicator)
-               replicator->add_receiver<P>(*this);
+               replicator->add_receiver(*this);
 }
 
-
 template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E> && HasEntityIdField<P>
-void RemoteEntityCallBase<P, E>::prepare(Handle<E> entity, P &packet)
+       requires ValidRemoteCall<P, E>
+void RemoteCall<P, E>::prepare(Handle<E> entity, P &packet) const
 {
        Handle<Zygote> zygote = entity->template get_component<Zygote>();
        if(!zygote)
-               throw std::invalid_argument("ReplicatedEntityCall::operator()");
+               throw std::invalid_argument("RemoteCall::prepare");
 
        std::uint32_t entity_id = zygote->get_entity_id();
        if(entity_id==Zygote::NO_ID)
-               throw std::invalid_argument("ReplicatedEntityCall::operator()");
+               throw std::invalid_argument("RemoteCall::prepare");
 
        packet.entity_id = entity_id;
 }
 
 template<typename P, typename E>
-       requires std::is_base_of_v<Entity, E> && HasEntityIdField<P>
-void RemoteEntityCallBase<P, E>::call(const P &packet)
+       requires ValidRemoteCall<P, E>
+void RemoteCall<P, E>::receive(P &&packet)
 {
-       Handle<Entity> entity = this->replicator->find_entity(packet.entity_id, this->replicator->is_server());
-       if(!entity)
-               return;  // TODO report the error somehow
+       if constexpr(std::is_same_v<E, void>)
+               this->func(packet);
+       else
+       {
+               Handle<Entity> entity = this->replicator->find_entity(packet.entity_id, this->replicator->is_server());
+               if(!entity)
+                       return;  // TODO report the error somehow
 
-       Handle<E> cast_entity = dynamic_handle_cast<E>(entity);
-       if(!cast_entity)
-               return;
+               Handle<E> cast_entity = dynamic_handle_cast<E>(entity);
+               if(!cast_entity)
+                       return;
 
-       this->func(cast_entity, packet);
+               this->func(cast_entity, packet);
+       }
 }
 
 
-template<typename P>
-void ReplicatedCall<P>::operator()(P &packet)
+template<typename P, typename E>
+void ReplicatedCall<P, E>::operator()(Handle<E> entity, P &packet)
 {
        if(this->replicator)
        {
                if(!this->replicator->is_server())
                        throw invalid_state("ReplicatedCall<P>::operator()");
-               this->replicator->send(packet);
+               this->prepare(entity, packet);
+               this->replicator->send(entity, packet);
        }
-       func(packet);
+       this->func(entity, packet);
 }
 
-template<typename P>
-void ReplicatedCall<P>::operator()(unsigned target, P &packet)
+template<typename P, typename E>
+void ReplicatedCall<P, E>::operator()(unsigned target, Handle<E> entity, P &packet)
 {
        if(this->replicator)
+       {
+               this->prepare(entity, packet);
                this->replicator->send(target, packet);
+       }
 }
 
 
 template<typename P>
-void RequestCall<P>::operator()(P &packet)
-{
-       if(this->replicator && !this->replicator->is_server())
-               this->replicator->send(packet);
-       else
-               this->func(packet);
-}
-
-
-template<typename P, typename E>
-void ReplicatedEntityCall<P, E>::operator()(Handle<E> entity, P &packet)
+void ReplicatedCall<P, void>::operator()(const P &packet)
 {
        if(this->replicator)
        {
-               this->prepare(entity, packet);
-               this->replicator->send(entity, packet);
+               if(!this->replicator->is_server())
+                       throw invalid_state("ReplicatedCall<P>::operator()");
+               this->replicator->send(packet);
        }
-       this->func(entity, packet);
+       this->func(packet);
 }
 
-template<typename P, typename E>
-void ReplicatedEntityCall<P, E>::operator()(unsigned target, Handle<E> entity, P &packet)
+template<typename P>
+void ReplicatedCall<P, void>::operator()(unsigned target, const P &packet)
 {
        if(this->replicator)
-       {
-               this->prepare(entity, packet);
                this->replicator->send(target, packet);
-       }
 }
 
 
 template<typename P, typename E>
-void EntityRequestCall<P, E>::operator()(Handle<E> entity, P &packet)
+void RequestCall<P, E>::operator()(Handle<E> entity, P &packet)
 {
        if(this->replicator && !this->replicator->is_server())
        {
@@ -196,6 +180,16 @@ void EntityRequestCall<P, E>::operator()(Handle<E> entity, P &packet)
                this->func(entity, packet);
 }
 
+
+template<typename P>
+void RequestCall<P, void>::operator()(P &packet)
+{
+       if(this->replicator && !this->replicator->is_server())
+               this->replicator->send(packet);
+       else
+               this->func(packet);
+}
+
 } // namespace Msp::Game
 
 #endif