#include "replicator.h"
#include <msp/core/raii.h>
+#include "possessed.h"
#include "spawner.h"
#include "transform.h"
#include "zygote.h"
Replicator::Replicator(Stage &s, Networking &n):
System(s),
+ event_source(stage.get_event_bus()),
observer(stage.get_event_bus()),
networking(n),
protocol(networking.set_receiver<StageProtocol>(&dispatcher))
observer.observe<Events::ComponentCreated>([this](const auto &e){ component_created(e); });
add_receiver<Messages::SpawnEntity>(*this);
+ add_receiver<Messages::GrantPossession>(*this);
}
void Replicator::add_spawner(Spawner &spawner, const string &type)
return (i!=entities.end() ? i->entity : nullptr);
}
+void Replicator::tick(Time::TimeDelta)
+{
+ stage.iterate_objects<Possessed>([this](Possessed &p){
+ if(p.has_changed())
+ {
+ auto i = lower_bound_member(entities, p.get_entity()->get_transform(), &ReplicatedEntity::transform);
+ if(i!=entities.end() && i->possessed.get()==&p)
+ {
+ event_source.emit<Events::PossessionChanged>(i->entity, p.get_player_id());
+ if(i->visible_to_players && is_server())
+ send_possession(*i, -1);
+ }
+ p.clear_changed();
+ }
+ });
+}
+
void Replicator::deferred_tick()
{
for(ReplicatedEntity &e: entities)
{
Handle<Entity> entity = zygote->get_entity();
Handle<Transform> transform = entity->get_transform();
+ Handle<Possessed> possessed = entity->get_component<Possessed>();
auto i = lower_bound_member(entities, transform, &ReplicatedEntity::transform);
- entities.emplace(i, entity, transform, zygote);
+ entities.emplace(i, entity, transform, zygote, possessed);
if(networking.is_server())
zygote->set_entity_id(next_entity_id++);
else if(received_entity_id!=Zygote::NO_ID)
zygote->set_entity_id(received_entity_id);
}
+ else if(Handle<Possessed> possessed = dynamic_handle_cast<Possessed>(event.component))
+ {
+ Handle<Transform> transform = possessed->get_entity()->get_transform();
+ auto i = lower_bound_member(entities, transform, &ReplicatedEntity::transform);
+ if(i!=entities.end() && i->transform==transform)
+ i->possessed = possessed;
+ }
}
void Replicator::send_spawn(const ReplicatedEntity &re, int target)
}
info.spawner->notify_spawn_sent(re.entity, target);
+
+ if(re.possessed && re.possessed->get_player_id())
+ send_possession(re, target);
+}
+
+void Replicator::send_possession(const ReplicatedEntity &re, int target)
+{
+ if(target<0 && players.empty())
+ return;
+
+ Messages::GrantPossession grant;
+ grant.entity_id = re.zygote->get_entity_id();
+ grant.player_id = re.possessed->get_player_id();
+
+ if(target>=0)
+ networking.send(target, grant);
+ else
+ {
+ for(unsigned p: players)
+ networking.send(p, grant);
+ }
}
void Replicator::receive(const Messages::SpawnEntity &message)
(*i)->spawn(type_name, setup_name, TransformValues(message.position, message.rotation, message.scale));
}
+void Replicator::receive(const Messages::GrantPossession &message)
+{
+ Handle<Entity> entity = find_entity(message.entity_id);
+ if(entity)
+ if(Handle<Possessed> possessed = entity->get_component<Possessed>())
+ possessed->set_player_id(message.player_id);
+}
+
} // namespace Msp::Game
namespace Msp::Game {
+class Possessed;
class Spawner;
class Transform;
-class MSPGAME_API Replicator: public System, private Net::PacketReceiver<Messages::SpawnEntity>
+class MSPGAME_API Replicator: public System, private Net::PacketReceiver<Messages::SpawnEntity>,
+ private Net::PacketReceiver<Messages::GrantPossession>
{
+public:
+ using EventSource = Game::EventSource<Events::PossessionChanged>;
+
private:
struct ReplicatedEntity
{
Handle<Entity> entity;
Handle<Transform> transform;
Handle<Zygote> zygote;
+ Handle<Possessed> possessed;
bool visible_to_players = false;
};
+ EventSource event_source;
EventObserver observer;
Networking &networking;
Net::DynamicDispatcher dispatcher;
void add_spawner(Spawner &, const std::string &);
void add_target_player(unsigned);
+ bool is_server() const { return networking.is_server(); }
template<typename P>
void add_receiver(Net::PacketReceiver<P> &);
Handle<Entity> find_entity(std::uint32_t) const;
- void tick(Time::TimeDelta) override { }
+ void tick(Time::TimeDelta) override;
void deferred_tick() override;
private:
void component_created(const Events::ComponentCreated &);
void send_spawn(const ReplicatedEntity &, int);
+ void send_possession(const ReplicatedEntity &, int);
void receive(const Messages::SpawnEntity &) override;
+ void receive(const Messages::GrantPossession &) override;
};
template<typename P>