implement server and client player join/leave notifications

This commit is contained in:
2024-07-22 12:58:40 +02:00
parent cbb2f5005e
commit 392eaeab83
23 changed files with 422 additions and 25 deletions

View File

@@ -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) {

View 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

View File

@@ -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