struct NetworkPlayerArrived
{
- unsigned id;
+ std::uint32_t id;
std::string name;
};
struct NetworkPlayerDeparted
{
- unsigned id;
+ std::uint32_t id;
};
struct EntityCreated
struct RemotePlayerEntered
{
- unsigned id;
+ std::uint32_t id;
};
struct PossessionChanged
{
Handle<Entity> entity;
- unsigned player_id;
+ std::uint32_t player_id;
};
struct RemotePlayerExited
{
- unsigned id;
+ std::uint32_t id;
};
} // namespace Events
return strings[id];
}
-void Networking::add_player(const string &name, function<void(unsigned)> callback)
+void Networking::add_player(const string &name, function<void(uint32_t)> callback)
{
if(state!=CONNECTED && state!=SERVER)
throw invalid_state("Networking::add_player");
}
}
-Networking::Player &Networking::create_player(const string &name, unsigned id)
+Networking::Player &Networking::create_player(const string &name, uint32_t id)
{
- Player &player = players.emplace_back();
- player.id = (id ? id : next_player_id++);
+ if(!(id&PLAYER_ID_MASK))
+ id |= next_player_id++;
+
+ auto i = lower_bound_member(players, id, &Player::id);
+
+ Player &player = *players.emplace(i);
+ player.id = id;
player.name = name;
return player;
}
void Networking::ServerConnection::receive(const Messages::PlayerRemoved &removed)
{
- auto i = find_member(networking.players, static_cast<unsigned>(removed.id), &Player::id);
+ auto i = lower_bound_member(networking.players, static_cast<uint32_t>(removed.id), &Player::id);
if(i!=networking.players.end())
{
networking.event_source.emit<Events::NetworkPlayerDeparted>(i->id);
Networking::ClientConnection::ClientConnection(Networking &n, unique_ptr<Net::StreamSocket> s):
- Connection(n, move(s))
+ Connection(n, move(s)),
+ id(networking.next_client_id++)
{
communicator.signal_protocol_ready.connect(sigc::mem_fun(this, &ClientConnection::protocol_ready));
communicator.add_protocol(networking.core_protocol, *this);
void Networking::ClientConnection::receive(const Messages::AddPlayerRequest &add_req)
{
- Player &player = networking.create_player(add_req.name);
+ Player &player = networking.create_player(add_req.name, id<<16);
player.owner = this;
Messages::AddPlayerResponse add_resp;
add_resp.token = add_req.token;
- add_resp.id = player.id;
+ add_resp.id = player.id&PLAYER_ID_MASK;
communicator.send(add_resp);
Messages::PlayerAdded added;
- added.id = player.id;
+ added.id = player.id&PLAYER_ID_MASK;
added.name = player.name;
for(const auto &c: networking.clients)
if(c.get()!=this)
{
private:
std::string active_stage;
+ std::uint16_t id = 0;
public:
ClientConnection(Networking &, std::unique_ptr<Net::StreamSocket>);
struct Player
{
ClientConnection *owner = nullptr;
- unsigned id = 0;
+ std::uint32_t id = 0;
std::string name;
- std::function<void(unsigned)> add_callback;
+ std::function<void(std::uint32_t)> add_callback;
};
- static constexpr unsigned ID_PENDING = 0x8000;
+ static constexpr std::uint32_t PLAYER_ID_MASK = 0xFFFF;
+ static constexpr std::uint32_t ID_PENDING = 0x8000;
Director &director;
EventSource event_source;
std::unique_ptr<ServerConnection> connection;
std::vector<std::unique_ptr<ClientConnection>> clients;
std::vector<Player> players;
- unsigned next_player_id = 1;
+ std::uint16_t next_client_id = 1;
+ std::uint16_t next_player_id = 1;
std::vector<std::string> strings;
Connection *current_sender = nullptr;
std::uint16_t intern_string(const std::string &);
const std::string &get_string(std::uint16_t) const;
- void add_player(const std::string &, std::function<void(unsigned)>);
+ void add_player(const std::string &, std::function<void(std::uint32_t)>);
private:
- Player &create_player(const std::string &, unsigned = 0);
+ Player &create_player(const std::string &, std::uint32_t = 0);
public:
template<typename P>
void send(const P &);
template<typename P>
- void send(unsigned, const P &);
+ void send(std::uint32_t, const P &);
+
+ template<typename P, typename F>
+ void send(const P &, F &&);
private:
void set_state(State);
}
template<typename P>
-void Networking::send(unsigned target, const P &packet)
+void Networking::send(std::uint32_t target, const P &packet)
{
if(state!=SERVER)
throw invalid_state("Networking::send");
i->owner->get_communicator().send(packet);
}
+template<typename P, typename F>
+void Networking::send(const P &packet, F &&filter)
+{
+ if(state!=SERVER)
+ throw invalid_state("Networking::send");
+
+ for(auto i=players.begin(); i!=players.end(); )
+ {
+ if(filter(i->id))
+ {
+ ClientConnection *client = i->owner;
+ client->get_communicator().send(packet);
+ for(; (i!=players.end() && i->owner==client); ++i) ;
+ }
+ else
+ ++i;
+ }
+}
+
namespace Events {
#include "possessed.h"
+using namespace std;
+
namespace Msp::Game {
-void Possessed::set_player_id(unsigned p)
+void Possessed::set_player_id(uint32_t p)
{
if(p!=player_id)
changed = true;
class MSPGAME_API Possessed: public Component
{
private:
- unsigned player_id = 0;
+ std::uint32_t player_id = 0;
bool changed = false;
public:
Possessed(Handle<Entity> e): Component(e) { }
- void set_player_id(unsigned);
- unsigned get_player_id() const { return player_id; }
+ void set_player_id(std::uint32_t);
+ std::uint32_t get_player_id() const { return player_id; }
bool has_changed() const { return changed; }
void clear_changed();
};
spawners.push_back(&spawner);
}
-void Replicator::add_target_player(unsigned id)
+void Replicator::add_target_player(uint32_t id)
{
- players.push_back(id);
+ auto i = lower_bound(players, id);
+ players.insert(i, id);
for(const ReplicatedEntity &e: entities)
send_spawn(e, id);
}
}
}
-void Replicator::send_spawn(const ReplicatedEntity &re, unsigned target)
+void Replicator::send_spawn(const ReplicatedEntity &re, uint32_t target)
{
if(!target && players.empty())
return;
send_possession(re, target);
}
-void Replicator::send_possession(const ReplicatedEntity &re, unsigned target)
+void Replicator::send_possession(const ReplicatedEntity &re, uint32_t target)
{
if(!target && players.empty())
return;
const Net::Protocol &protocol;
std::vector<Spawner *> spawners;
std::vector<ReplicatedEntity> entities;
- std::vector<unsigned> players;
+ std::vector<std::uint32_t> players;
std::uint32_t next_entity_id = 1;
std::uint32_t received_entity_id = Zygote::NO_ID;
Replicator(Stage &, Networking &);
void add_spawner(Spawner &, const std::string &);
- void add_target_player(unsigned);
+ void add_target_player(std::uint32_t);
bool is_server() const { return networking.is_server(); }
template<typename P>
void send(Handle<Entity>, const P &);
template<typename P>
- void send(unsigned, const P &);
+ void send(std::uint32_t, const P &);
Handle<Entity> find_entity(std::uint32_t) const;
private:
void component_created(const Events::ComponentCreated &);
- void send_spawn(const ReplicatedEntity &, unsigned);
- void send_possession(const ReplicatedEntity &, unsigned);
+ void send_spawn(const ReplicatedEntity &, std::uint32_t);
+ void send_possession(const ReplicatedEntity &, std::uint32_t);
void receive(const Messages::SpawnEntity &) override;
void receive(const Messages::GrantPossession &) override;
template<typename P>
void Replicator::send(const P &packet)
{
- for(unsigned p: players)
- networking.send(p, packet);
+ networking.send(packet, [this, i=0u](std::uint32_t player_id) mutable {
+ if(i<players.size() && players[i]==player_id)
+ {
+ ++i;
+ return true;
+ }
+ return false;
+ });
}
template<typename P>
}
template<typename P>
-void Replicator::send(unsigned target, const P &packet)
+void Replicator::send(std::uint32_t target, const P &packet)
{
if(target)
networking.send(target, packet);
handler.spawned(move(entity));
}
-void Spawner::notify_spawn_sent(Handle<Entity> entity, unsigned target) const
+void Spawner::notify_spawn_sent(Handle<Entity> entity, uint32_t target) const
{
handler.spawn_sent(entity, target);
}
{
public:
virtual void spawned(Owned<Entity>) = 0;
- virtual void spawn_sent(Handle<Entity>, unsigned) { }
+ virtual void spawn_sent(Handle<Entity>, std::uint32_t) { }
};
void spawn(const SpawnableType &, const std::string &, const TransformValues &);
public:
- void notify_spawn_sent(Handle<Entity>, unsigned) const;
+ void notify_spawn_sent(Handle<Entity>, std::uint32_t) const;
};