From 89d5ad5f5457883a23620a98652897dfe2521a27 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Tue, 23 Jul 2024 01:10:20 +0200 Subject: [PATCH] true atomic EnttWorld --- include/blitz/common/Types.h | 24 ++++++++++++++++++- include/blitz/protocol/PacketHandler.h | 3 --- include/client/Client.h | 2 +- include/server/Server.h | 2 +- include/server/systems/DisconnectSystem.h | 5 ++-- include/server/systems/KeepAliveSystem.h | 5 ++-- src/client/Client.cpp | 4 +--- src/client/handlers/LoggingSuccessHandler.cpp | 2 +- src/client/handlers/PlayerJoinHandler.cpp | 2 +- src/client/handlers/PlayerLeaveHandler.cpp | 2 +- src/client/handlers/PlayerListHandler.cpp | 2 +- src/server/Server.cpp | 11 ++++----- src/server/handlers/KeepAliveHandler.cpp | 2 +- src/server/handlers/PlayerLoginHandler.cpp | 2 +- src/server/systems/DisconnectSystem.cpp | 16 ++++++++----- src/server/systems/KeepAliveSystem.cpp | 12 ++++++---- 16 files changed, 61 insertions(+), 35 deletions(-) diff --git a/include/blitz/common/Types.h b/include/blitz/common/Types.h index 549c39a..2c4d977 100644 --- a/include/blitz/common/Types.h +++ b/include/blitz/common/Types.h @@ -1,9 +1,31 @@ #pragma once -#include +#include namespace blitz { +struct AtomicEnttWorld { + Nz::EnttWorld& m_World; + std::lock_guard m_LockGuard; + + Nz::EnttWorld* operator->() { + return &m_World; + } +}; + +struct EnttWorld { + Nz::EnttWorld& m_World; + std::mutex m_Mutex; + + /** + * \return an AtomicEnttWorld structure which will lock the associated mutex until destruction + * \warning Do not hold more than one instance or the current thread will self lock + */ + operator AtomicEnttWorld() { + return {m_World, std::lock_guard(m_Mutex)}; + } +}; + using EntityID = std::uint32_t; } // namespace blitz diff --git a/include/blitz/protocol/PacketHandler.h b/include/blitz/protocol/PacketHandler.h index 4383b65..c499bf6 100644 --- a/include/blitz/protocol/PacketHandler.h +++ b/include/blitz/protocol/PacketHandler.h @@ -4,9 +4,6 @@ #include namespace blitz { - -using EnttWorld = std::atomic>; - namespace protocol { class PacketHandler : private NonCopyable { diff --git a/include/client/Client.h b/include/client/Client.h index 9debeaa..f5fc634 100644 --- a/include/client/Client.h +++ b/include/client/Client.h @@ -10,7 +10,7 @@ namespace client { class Client : private NonCopyable { public: - Client(std::shared_ptr a_World); + Client(Nz::EnttWorld& a_World); ~Client(); void Connect(const Nz::IpAddress& a_Ip); diff --git a/include/server/Server.h b/include/server/Server.h index 2bc1f4f..8fbd892 100644 --- a/include/server/Server.h +++ b/include/server/Server.h @@ -12,7 +12,7 @@ class Server { * \brief Construct a server * \pre Two instances of Server should not share the same world */ - Server(std::uint16_t a_Port, std::shared_ptr a_World); + Server(std::uint16_t a_Port, Nz::EnttWorld& a_World); ~Server(); network::EnetConnection* GetConnection(std::uint16_t a_PeerId); diff --git a/include/server/systems/DisconnectSystem.h b/include/server/systems/DisconnectSystem.h index 049ba03..da5c055 100644 --- a/include/server/systems/DisconnectSystem.h +++ b/include/server/systems/DisconnectSystem.h @@ -2,6 +2,7 @@ #include #include +#include namespace blitz { namespace server { @@ -10,12 +11,12 @@ class Server; class DisconectSystem { public: - DisconectSystem(entt::registry& a_Registry, Server& a_Server); + DisconectSystem(entt::registry&, EnttWorld& a_World, Server& a_Server); void Update(Nz::Time elapsedTime); private: - entt::registry& m_Registry; + EnttWorld& m_World; Server& m_Server; }; diff --git a/include/server/systems/KeepAliveSystem.h b/include/server/systems/KeepAliveSystem.h index b2426c0..075b6d8 100644 --- a/include/server/systems/KeepAliveSystem.h +++ b/include/server/systems/KeepAliveSystem.h @@ -2,18 +2,19 @@ #include #include +#include namespace blitz { namespace server { class KeepAliveSystem { public: - KeepAliveSystem(entt::registry& a_Registry); + KeepAliveSystem(entt::registry&, EnttWorld& a_World); void Update(Nz::Time elapsedTime); private: - entt::registry& m_Registry; + EnttWorld& m_World; }; } // namespace server diff --git a/src/client/Client.cpp b/src/client/Client.cpp index ef34c30..644b03d 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -11,9 +11,7 @@ namespace blitz { namespace client { -Client::Client(std::shared_ptr a_World) { - m_World.store(a_World); -} +Client::Client(Nz::EnttWorld& a_World) : m_World({a_World}) {} Client::~Client() { Disconnect(); diff --git a/src/client/handlers/LoggingSuccessHandler.cpp b/src/client/handlers/LoggingSuccessHandler.cpp index 1d0adde..1f70390 100644 --- a/src/client/handlers/LoggingSuccessHandler.cpp +++ b/src/client/handlers/LoggingSuccessHandler.cpp @@ -11,7 +11,7 @@ LoggingSuccessHandler::LoggingSuccessHandler(network::EnetConnection& a_Connecti } void LoggingSuccessHandler::Handle(const blitz::protocol::data::LoggingSuccess& a_LoggingSuccess) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; auto player = world->CreateEntity(); player.emplace(a_LoggingSuccess.m_PlayerId); } diff --git a/src/client/handlers/PlayerJoinHandler.cpp b/src/client/handlers/PlayerJoinHandler.cpp index 73d0c70..8541c52 100644 --- a/src/client/handlers/PlayerJoinHandler.cpp +++ b/src/client/handlers/PlayerJoinHandler.cpp @@ -11,7 +11,7 @@ PlayerJoinHandler::PlayerJoinHandler(network::EnetConnection& a_Connection, Entt } void PlayerJoinHandler::Handle(const protocol::data::PlayerJoin& a_PlayerJoin) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; assert(world->GetRegistry().view().size() == 1 && "There should be only one local player !"); auto localPlayer = world->GetRegistry().view().front(); diff --git a/src/client/handlers/PlayerLeaveHandler.cpp b/src/client/handlers/PlayerLeaveHandler.cpp index 7d01d78..e0fe1c9 100644 --- a/src/client/handlers/PlayerLeaveHandler.cpp +++ b/src/client/handlers/PlayerLeaveHandler.cpp @@ -9,7 +9,7 @@ PlayerLeaveHandler::PlayerLeaveHandler(network::EnetConnection& a_Connection, En } void PlayerLeaveHandler::Handle(const protocol::data::PlayerLeave& a_PlayerLeave) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; entt::entity playerLeft; diff --git a/src/client/handlers/PlayerListHandler.cpp b/src/client/handlers/PlayerListHandler.cpp index 997aa67..c19fa36 100644 --- a/src/client/handlers/PlayerListHandler.cpp +++ b/src/client/handlers/PlayerListHandler.cpp @@ -9,7 +9,7 @@ PlayerListHandler::PlayerListHandler(network::EnetConnection& a_Connection, Entt } void PlayerListHandler::Handle(const protocol::data::PlayerList& a_PlayerList) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; for (auto playerInfo : a_PlayerList.m_Players) { auto player = world->CreateEntity(); player.emplace(playerInfo); diff --git a/src/server/Server.cpp b/src/server/Server.cpp index 4f6e232..f2e9a37 100644 --- a/src/server/Server.cpp +++ b/src/server/Server.cpp @@ -14,8 +14,7 @@ namespace server { #define RegisterHandler(Handler) session.m_Handlers.push_back(std::make_unique(*session.m_Connection, m_World)) -Server::Server(std::uint16_t a_Port, std::shared_ptr a_World) : m_NetworkServer(a_Port) { - m_World.store(a_World); +Server::Server(std::uint16_t a_Port, Nz::EnttWorld& a_World) : m_World({a_World}), m_NetworkServer(a_Port) { RegisterSystems(); m_NetworkServer.OnClientConnect.Connect(this, &Server::HandleConnect); m_NetworkServer.OnClientDisconnect.Connect(this, &Server::HandleDisconnect); @@ -40,7 +39,7 @@ void Server::HandleDisconnect(network::EnetConnection& a_Connection) { } void Server::CreateEntity(network::EnetConnection& a_Connection) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; auto entity = world->CreateEntity(); @@ -48,9 +47,9 @@ void Server::CreateEntity(network::EnetConnection& a_Connection) { } void Server::RegisterSystems() { - auto world = m_World.load(); - world->AddSystem(); - world->AddSystem(*this); + AtomicEnttWorld world = m_World; + world->AddSystem(m_World); + world->AddSystem(m_World, *this); auto counter = world->CreateEntity(); counter.emplace(0); diff --git a/src/server/handlers/KeepAliveHandler.cpp b/src/server/handlers/KeepAliveHandler.cpp index a979bd8..1fe9725 100644 --- a/src/server/handlers/KeepAliveHandler.cpp +++ b/src/server/handlers/KeepAliveHandler.cpp @@ -16,7 +16,7 @@ KeepAliveHandler::KeepAliveHandler(network::EnetConnection& a_Connection, EnttWo KeepAliveHandler::~KeepAliveHandler() {} void KeepAliveHandler::Handle(std::uint16_t a_PeerId, const protocol::data::KeepAlive& a_KeepAlive) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; world->GetRegistry().view().each([a_PeerId, &a_KeepAlive](auto& keepAliveSession) { if (keepAliveSession.m_PeerId == a_PeerId && keepAliveSession.m_LastKeepAliveId == a_KeepAlive.m_KeepAliveId) { keepAliveSession.m_LastTime = Nz::GetElapsedMilliseconds(); diff --git a/src/server/handlers/PlayerLoginHandler.cpp b/src/server/handlers/PlayerLoginHandler.cpp index 0119349..1cf66aa 100644 --- a/src/server/handlers/PlayerLoginHandler.cpp +++ b/src/server/handlers/PlayerLoginHandler.cpp @@ -18,7 +18,7 @@ PlayerLoginHandler::PlayerLoginHandler(network::EnetConnection& a_Connection, En PlayerLoginHandler::~PlayerLoginHandler() {} void PlayerLoginHandler::Handle(std::uint16_t a_PeerId, const protocol::data::PlayerLogin& a_PlayerLogin) { - auto world = m_World.load(); + AtomicEnttWorld world = m_World; std::vector players; diff --git a/src/server/systems/DisconnectSystem.cpp b/src/server/systems/DisconnectSystem.cpp index 93e0c38..ebb49a8 100644 --- a/src/server/systems/DisconnectSystem.cpp +++ b/src/server/systems/DisconnectSystem.cpp @@ -8,29 +8,33 @@ namespace blitz { namespace server { -DisconectSystem::DisconectSystem(entt::registry& a_Registry, Server& a_Server) : m_Registry(a_Registry), m_Server(a_Server) {} +DisconectSystem::DisconectSystem(entt::registry&, EnttWorld& a_World, Server& a_Server) : m_World(a_World), m_Server(a_Server) {} void DisconectSystem::Update(Nz::Time elapsedTime) { - auto disconnects = m_Registry.view(); + AtomicEnttWorld world = m_World; + + entt::registry& registry = world->GetRegistry(); + + auto disconnects = registry.view(); // broadcast player leave for (auto entity : disconnects) { - auto* player = m_Registry.try_get(entity); + auto* player = registry.try_get(entity); if (player) { - for (auto [entity, connection] : m_Registry.view().each()) { + for (auto [entity, connection] : registry.view().each()) { connection.m_Connection->SendPlayerLeave({player->m_PlayerId}); } } } // close connections - m_Registry.view().each( + registry.view().each( [this](auto entity, EnetConnectionComponent& connection, DisconnectComponent disconnect) { m_Server.CloseConnection(connection.m_Connection->GetPeerId()); }); // remove the entities - m_Registry.destroy(disconnects.begin(), disconnects.end()); + registry.destroy(disconnects.begin(), disconnects.end()); } } // namespace server diff --git a/src/server/systems/KeepAliveSystem.cpp b/src/server/systems/KeepAliveSystem.cpp index c267947..959c71c 100644 --- a/src/server/systems/KeepAliveSystem.cpp +++ b/src/server/systems/KeepAliveSystem.cpp @@ -9,11 +9,15 @@ namespace blitz { namespace server { -KeepAliveSystem::KeepAliveSystem(entt::registry& a_Registry) : m_Registry(a_Registry) {} +KeepAliveSystem::KeepAliveSystem(entt::registry&, EnttWorld& a_World) : m_World(a_World) {} void KeepAliveSystem::Update(Nz::Time elapsedTime) { - m_Registry.view().each( - [this](auto entity, auto& keepAliveSession, auto& connection) { + AtomicEnttWorld world = m_World; + + entt::registry& registry = world->GetRegistry(); + + registry.view().each( + [®istry](auto entity, auto& keepAliveSession, auto& connection) { auto duration = Nz::GetElapsedMilliseconds() - keepAliveSession.m_LastTime; if (duration > Nz::Time::Seconds(10)) { if (keepAliveSession.m_RecievedResponse) { @@ -28,7 +32,7 @@ void KeepAliveSystem::Update(Nz::Time elapsedTime) { connection.m_Connection->SendKeepAlive({keepAliveId}); } else { // We kick the player because he's not responding anymore - m_Registry.emplace(entity); + registry.emplace(entity); } } });