return player;
}
+bool Networking::is_current_sender(uint32_t player_id) const
+{
+ auto i = lower_bound_member(players, player_id, &Player::id);
+ if(i==players.end() || i->id!=player_id)
+ return false;
+
+ return i->owner==current_sender;
+}
+
void Networking::set_state(State s)
{
if(s==state)
template<typename P, typename F>
void send(const P &, F &&);
+ bool is_current_sender(std::uint32_t) const;
+
private:
void set_state(State);
void protocol_ready(const Net::Protocol &);
requires std::is_base_of_v<Entity, E> && HasEntityIdField<P>
void RemoteEntityCallBase<P, E>::call(const P &packet)
{
- Handle<Entity> entity = this->replicator->find_entity(packet.entity_id);
+ Handle<Entity> entity = this->replicator->find_entity(packet.entity_id, this->replicator->is_server());
if(!entity)
return; // TODO report the error somehow
namespace Msp::Game {
+entity_access_denied::entity_access_denied(uint32_t entity_id):
+ runtime_error(lexical_cast<string>(entity_id))
+{ }
+
+
Replicator::Replicator(Stage &s, Networking &n):
System(s),
event_source(stage.get_event_bus()),
add_receiver<Messages::GrantPossession>(*this);
}
-Handle<Entity> Replicator::find_entity(uint32_t id) const
+Handle<Entity> Replicator::find_entity(uint32_t id, bool check_access) const
{
auto i = find_if(entities, [id](const ReplicatedEntity &e){ return e.zygote->get_entity_id()==id; });
+ if(check_access)
+ {
+ uint32_t possessor = (i->possessed ? i->possessed->get_player_id() : 0);
+ if(!possessor || !networking.is_current_sender(possessor))
+ throw entity_access_denied(id);
+ }
return (i!=entities.end() ? i->entity : nullptr);
}
class Spawner;
class Transform;
+class entity_access_denied: public std::runtime_error
+{
+public:
+ entity_access_denied(std::uint32_t);
+};
+
+
class MSPGAME_API Replicator: public System, private Net::PacketReceiver<Messages::SpawnEntity>,
private Net::PacketReceiver<Messages::GrantPossession>
{
template<typename P>
void send(std::uint32_t, const P &);
- Handle<Entity> find_entity(std::uint32_t) const;
+ Handle<Entity> find_entity(std::uint32_t, bool = false) const;
void tick(Time::TimeDelta) override;
void deferred_tick() override;