implement server and client player join/leave notifications
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
#include <server/Server.h>
|
||||
|
||||
#include <server/components/EnetConnection.h>
|
||||
#include <server/components/KeepAliveSession.h>
|
||||
#include <server/components/ServerIdCounter.h>
|
||||
|
||||
#include <server/handlers/KeepAliveHandler.h>
|
||||
#include <server/handlers/PlayerLoginHandler.h>
|
||||
|
||||
#include <server/systems/DisconnectSystem.h>
|
||||
#include <server/systems/KeepAliveSystem.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
#define RegisterHandler(Handler) session.m_Handlers.push_back(std::make_unique<Handler>(*session.m_Connection, m_World))
|
||||
|
||||
Server::Server(std::uint16_t a_Port, std::shared_ptr<Nz::EnttWorld> a_World) : m_NetworkServer(a_Port) {
|
||||
m_World.store(a_World);
|
||||
RegisterSystems();
|
||||
@@ -39,7 +44,6 @@ void Server::CreateEntity(network::EnetConnection& a_Connection) {
|
||||
|
||||
auto entity = world->CreateEntity();
|
||||
|
||||
entity.emplace<KeepAliveSessionComponent>(a_Connection.GetPeerId(), 69, Nz::GetElapsedMilliseconds(), true);
|
||||
entity.emplace<EnetConnectionComponent>(&a_Connection);
|
||||
}
|
||||
|
||||
@@ -47,10 +51,14 @@ void Server::RegisterSystems() {
|
||||
auto world = m_World.load();
|
||||
world->AddSystem<KeepAliveSystem>();
|
||||
world->AddSystem<DisconectSystem>(*this);
|
||||
|
||||
auto counter = world->CreateEntity();
|
||||
counter.emplace<ServerIdCounterComponent>(0);
|
||||
}
|
||||
|
||||
void Server::RegisterHandlers(Session& session) {
|
||||
session.m_Handlers.push_back(std::make_unique<KeepAliveHandler>(*session.m_Connection, m_World));
|
||||
RegisterHandler(KeepAliveHandler);
|
||||
RegisterHandler(PlayerLoginHandler);
|
||||
}
|
||||
|
||||
network::EnetConnection* Server::GetConnection(std::uint16_t a_PeerId) {
|
||||
|
||||
68
src/server/handlers/PlayerLoginHandler.cpp
Normal file
68
src/server/handlers/PlayerLoginHandler.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <server/handlers/PlayerLoginHandler.h>
|
||||
|
||||
#include <Nazara/Core/Time.hpp>
|
||||
#include <blitz/components/PlayerInfo.h>
|
||||
#include <server/components/EnetConnection.h>
|
||||
#include <server/components/KeepAliveSession.h>
|
||||
#include <server/components/ServerIdCounter.h>
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
PlayerLoginHandler::PlayerLoginHandler(network::EnetConnection& a_Connection, EnttWorld& a_World) :
|
||||
protocol::PacketHandler(a_Connection, a_World) {
|
||||
m_Slot.Connect(a_Connection.OnPlayerLogin,
|
||||
[this](const protocol::data::PlayerLogin& a_PlayerLogin) { Handle(m_Connection.GetPeerId(), a_PlayerLogin); });
|
||||
}
|
||||
|
||||
PlayerLoginHandler::~PlayerLoginHandler() {}
|
||||
|
||||
void PlayerLoginHandler::Handle(std::uint16_t a_PeerId, const protocol::data::PlayerLogin& a_PlayerLogin) {
|
||||
auto world = m_World.load();
|
||||
|
||||
std::vector<PlayerInfoComponent> players;
|
||||
|
||||
for (auto [entity, playerInfo] : world->GetRegistry().view<PlayerInfoComponent>().each()) {
|
||||
players.push_back(playerInfo);
|
||||
}
|
||||
|
||||
assert(world->GetRegistry().view<ServerIdCounterComponent>().size() == 1 && "There should be only one counter !");
|
||||
|
||||
auto& serverCounter =
|
||||
world->GetRegistry().get<ServerIdCounterComponent>(world->GetRegistry().view<ServerIdCounterComponent>().front());
|
||||
|
||||
EntityID newEntityId = serverCounter.m_NextEntityId++;
|
||||
|
||||
PlayerInfoComponent newPlayer;
|
||||
|
||||
for (auto [entity, connection] : world->GetRegistry().view<EnetConnectionComponent>().each()) {
|
||||
if (connection.m_Connection->GetPeerId() == m_Connection.GetPeerId()) {
|
||||
// players should not try to log in twice
|
||||
auto previousPlayerInfo = world->GetRegistry().try_get<PlayerInfoComponent>(entity);
|
||||
if (previousPlayerInfo)
|
||||
return;
|
||||
|
||||
newPlayer = world->GetRegistry().emplace<PlayerInfoComponent>(entity, newEntityId, a_PlayerLogin.m_PlayerName);
|
||||
|
||||
world->GetRegistry().emplace<KeepAliveSessionComponent>(
|
||||
entity, m_Connection.GetPeerId(), 69, Nz::GetElapsedMilliseconds(), true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send logging success
|
||||
m_Connection.SendLoggingSuccess({newEntityId});
|
||||
|
||||
// send player list
|
||||
if (!players.empty())
|
||||
m_Connection.SendPlayerList({players});
|
||||
|
||||
// broadcast player join
|
||||
for (auto [entity, connection] : world->GetRegistry().view<EnetConnectionComponent>().each()) {
|
||||
connection.m_Connection->SendPlayerJoin({newPlayer});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
@@ -11,14 +11,26 @@ namespace server {
|
||||
DisconectSystem::DisconectSystem(entt::registry& a_Registry, Server& a_Server) : m_Registry(a_Registry), m_Server(a_Server) {}
|
||||
|
||||
void DisconectSystem::Update(Nz::Time elapsedTime) {
|
||||
auto disconnects = m_Registry.view<DisconnectComponent>();
|
||||
|
||||
// broadcast player leave
|
||||
for (auto entity : disconnects) {
|
||||
auto* player = m_Registry.try_get<PlayerInfoComponent>(entity);
|
||||
if (player) {
|
||||
for (auto [entity, connection] : m_Registry.view<EnetConnectionComponent>().each()) {
|
||||
connection.m_Connection->SendPlayerLeave({player->m_PlayerId});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close connections
|
||||
m_Registry.view<EnetConnectionComponent, DisconnectComponent>().each(
|
||||
[this](auto entity, EnetConnectionComponent& connection, DisconnectComponent disconnect) {
|
||||
m_Server.CloseConnection(connection.m_Connection->GetPeerId());
|
||||
});
|
||||
|
||||
// remove the entities
|
||||
auto it = m_Registry.view<DisconnectComponent>();
|
||||
m_Registry.destroy(it.begin(), it.end());
|
||||
m_Registry.destroy(disconnects.begin(), disconnects.end());
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
|
||||
Reference in New Issue
Block a user