Stage &stage;
};
+struct ServerStageActivated
+{
+ std::string name;
+ Stage *local_stage = nullptr;
+};
+
struct StageDeactivated
{
Stage &stage;
Handle<Camera> camera;
};
+struct RemotePlayerEntered
+{
+ unsigned id;
+};
+
+struct RemotePlayerExited
+{
+ unsigned id;
+};
+
} // namespace Events
} // namespace Msp::Game
std::string value;
};
+struct StageActivated
+{
+ std::uint16_t name;
+};
+
} // namespace Messages
} // namespace Msp::Game
#include <msp/net/inet6.h>
#include <msp/net/resolve.h>
#include "director.h"
+#include "stage.h"
using namespace std;
namespace Msp::Game {
Networking::Networking(Director &d):
- event_source(d.get_event_bus()),
- io_disp(d.get_io_dispatcher())
+ director(d),
+ event_source(director.get_event_bus()),
+ observer(director.get_event_bus()),
+ io_disp(director.get_io_dispatcher())
{
+ observer.observe<Events::StageActivated>([this](const auto &e){ stage_activated(e); });
+
strings.emplace_back();
}
{
unique_ptr<Net::StreamSocket> socket(server_socket->accept());
clients.emplace_back(make_unique<ClientConnection>(*this, move(socket)));
+
+}
+
+void Networking::stage_activated(const Events::StageActivated &event)
+{
+ if(!is_active())
+ return;
+
+ Messages::StageActivated message;
+ message.name = intern_string(event.stage.get_name());
+ if(state==SERVER)
+ {
+ for(const auto &c: clients)
+ c->get_communicator().send(message);
+ }
+ else if(state==CONNECTED)
+ connection->get_communicator().send(message);
}
networking.strings[intern.id] = intern.value;
}
+void Networking::ServerConnection::receive(const Messages::StageActivated &activated)
+{
+ string name = networking.get_string(activated.name);
+ Stage *local_stage = networking.director.find_stage(name);
+ networking.event_source.emit<Events::ServerStageActivated>(name, local_stage);
+}
+
Networking::ClientConnection::ClientConnection(Networking &n, unique_ptr<Net::StreamSocket> s):
Connection(n, move(s))
networking.event_source.emit<Events::NetworkPlayerArrived>(player.id, player.name);
}
+void Networking::ClientConnection::receive(const Messages::StageActivated &activated)
+{
+ const string &new_active_stage = networking.get_string(activated.name);
+ if(new_active_stage==active_stage)
+ return;
+
+ string old_active_stage = move(active_stage);
+ active_stage = new_active_stage;
+
+ if(Stage *local_active_stage = networking.director.get_active_stage())
+ {
+ bool entered = (active_stage==local_active_stage->get_name());
+ bool exited = (old_active_stage==local_active_stage->get_name());
+ for(const Player &p: networking.players)
+ if(p.owner==this)
+ {
+ if(entered)
+ local_active_stage->get_event_source().emit<Events::RemotePlayerEntered>(p.id);
+ else if(exited)
+ local_active_stage->get_event_source().emit<Events::RemotePlayerExited>(p.id);
+ }
+ }
+}
+
} // namespace Msp::Game
public Net::PacketReceiver<Messages::AddPlayerResponse>,
public Net::PacketReceiver<Messages::PlayerAdded>,
public Net::PacketReceiver<Messages::PlayerRemoved>,
- public Net::PacketReceiver<Messages::InternString>
+ public Net::PacketReceiver<Messages::InternString>,
+ public Net::PacketReceiver<Messages::StageActivated>
{
public:
ServerConnection(Networking &, const Net::SockAddr &);
void receive(const Messages::PlayerAdded &) override;
void receive(const Messages::PlayerRemoved &) override;
void receive(const Messages::InternString &) override;
+ void receive(const Messages::StageActivated &) override;
};
class ClientConnection: public Connection,
- public Net::PacketReceiver<Messages::AddPlayerRequest>
+ public Net::PacketReceiver<Messages::AddPlayerRequest>,
+ public Net::PacketReceiver<Messages::StageActivated>
{
+ private:
+ std::string active_stage;
+
public:
ClientConnection(Networking &, std::unique_ptr<Net::StreamSocket>);
void protocol_ready(const Net::Protocol &);
void receive(const Messages::AddPlayerRequest &) override;
+ void receive(const Messages::StageActivated &) override;
};
struct Player
static constexpr unsigned ID_PENDING = 0x8000;
+ Director &director;
EventSource event_source;
+ EventObserver observer;
IO::EventDispatcher &io_disp;
Protocol protocol;
State state = DISABLED;
void start_server(unsigned);
void connect_to_server(const std::string &);
+ bool is_active() const { return state==SERVER || state==CONNECTED; }
bool is_server() const { return state==DISABLED || state==SERVER; }
void disable();
void reap_connections();
void set_state(State);
void protocol_ready(const Net::Protocol &);
void incoming_connection();
+
+ void stage_activated(const Events::StageActivated &);
};
add<AddPlayerResponse>(&AddPlayerResponse::token, &AddPlayerResponse::id);
add<PlayerAdded>(&PlayerAdded::id, &PlayerAdded::name);
add<InternString>(&InternString::id, &InternString::value);
+ add<StageActivated>(&StageActivated::name);
}
} // namespace Msp::Game
{
public:
using EventSource = Game::EventSource<Events::EntityCreated, Events::EntityDestroyed,
- Events::ComponentCreated, Events::ComponentDestroyed, Events::CameraChanged>;
+ Events::ComponentCreated, Events::ComponentDestroyed, Events::CameraChanged,
+ Events::RemotePlayerEntered, Events::RemotePlayerExited>;
private:
std::string name;