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))
{
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