From d87a1d390c951e12322bafd1d601242b3c4cf918 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Thu, 22 Feb 2024 20:16:49 +0100 Subject: [PATCH] Server: Add limit to concurrent chunk create packets to avoid overload network --- include/CommonLib/NetworkReactor.hpp | 3 ++- include/CommonLib/NetworkSession.hpp | 2 +- include/CommonLib/NetworkSession.inl | 4 ++-- include/CommonLib/Protocol/Packets.hpp | 3 +-- include/ServerLib/SessionVisibilityHandler.hpp | 3 +++ include/ServerLib/SessionVisibilityHandler.inl | 1 + src/CommonLib/NetworkReactor.cpp | 11 +++++++++-- src/ServerLib/SessionVisibilityHandler.cpp | 13 +++++++++++-- 8 files changed, 30 insertions(+), 10 deletions(-) diff --git a/include/CommonLib/NetworkReactor.hpp b/include/CommonLib/NetworkReactor.hpp index 502bd331..d3b106b1 100644 --- a/include/CommonLib/NetworkReactor.hpp +++ b/include/CommonLib/NetworkReactor.hpp @@ -47,7 +47,7 @@ namespace tsom void QueryInfo(std::size_t peerId, PeerInfoCallback callback); - void SendData(std::size_t peerId, Nz::UInt8 channelId, Nz::ENetPacketFlags flags, Nz::NetPacket&& packet); + void SendData(std::size_t peerId, Nz::UInt8 channelId, Nz::ENetPacketFlags flags, Nz::NetPacket&& packet, std::function acknowledgeCallback = {}); NetworkReactor& operator=(const NetworkReactor&) = delete; NetworkReactor& operator=(NetworkReactor&&) = delete; @@ -124,6 +124,7 @@ namespace tsom Nz::ENetPacketFlags flags; Nz::UInt8 channelId; Nz::NetPacket packet; + std::function acknowledgeCallback; }; struct QueryPeerInfo diff --git a/include/CommonLib/NetworkSession.hpp b/include/CommonLib/NetworkSession.hpp index ea63d3a8..7e40b544 100644 --- a/include/CommonLib/NetworkSession.hpp +++ b/include/CommonLib/NetworkSession.hpp @@ -37,7 +37,7 @@ namespace tsom void HandlePacket(Nz::NetPacket&& netPacket); - template void SendPacket(const T& packet); + template void SendPacket(const T& packet, std::function acknowledgeCallback = {}); SessionHandler& SetHandler(std::unique_ptr&& sessionHandler); template T& SetupHandler(Args&&... args); diff --git a/include/CommonLib/NetworkSession.inl b/include/CommonLib/NetworkSession.inl index d2444217..906d5ad2 100644 --- a/include/CommonLib/NetworkSession.inl +++ b/include/CommonLib/NetworkSession.inl @@ -23,7 +23,7 @@ namespace tsom } template - void NetworkSession::SendPacket(const T& packet) + void NetworkSession::SendPacket(const T& packet, std::function acknowledgeCallback) { static_assert(PacketCount < 0xFF); @@ -37,7 +37,7 @@ namespace tsom netPacket.FlushBits(); - m_reactor.SendData(m_peerId, sendAttributes.channelId, sendAttributes.flags, std::move(netPacket)); + m_reactor.SendData(m_peerId, sendAttributes.channelId, sendAttributes.flags, std::move(netPacket), std::move(acknowledgeCallback)); } template diff --git a/include/CommonLib/Protocol/Packets.hpp b/include/CommonLib/Protocol/Packets.hpp index f43d48ff..b4197115 100644 --- a/include/CommonLib/Protocol/Packets.hpp +++ b/include/CommonLib/Protocol/Packets.hpp @@ -119,14 +119,13 @@ namespace tsom struct ChunkUpdate { - Helper::ChunkId chunkId; - struct BlockUpdate { Helper::VoxelLocation voxelLoc; Nz::UInt8 newContent; }; + Helper::ChunkId chunkId; std::vector updates; }; diff --git a/include/ServerLib/SessionVisibilityHandler.hpp b/include/ServerLib/SessionVisibilityHandler.hpp index 522bc179..41191793 100644 --- a/include/ServerLib/SessionVisibilityHandler.hpp +++ b/include/ServerLib/SessionVisibilityHandler.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace tsom { @@ -59,6 +60,7 @@ namespace tsom void DispatchChunks(); void DispatchEntities(Nz::UInt16 tickIndex); + static constexpr std::size_t MaxConcurrentChunkUpdate = 3; static constexpr std::size_t FreeChunkIdGrowRate = 128; static constexpr std::size_t FreeEntityIdGrowRate = 512; @@ -80,6 +82,7 @@ namespace tsom tsl::hopscotch_set m_deletedEntities; tsl::hopscotch_set m_movingEntities; tsl::hopscotch_map m_chunkIndices; + std::shared_ptr m_activeChunkUpdates; std::vector m_visibleChunks; Nz::Bitset m_freeChunkIds; Nz::Bitset m_freeEntityIds; diff --git a/include/ServerLib/SessionVisibilityHandler.inl b/include/ServerLib/SessionVisibilityHandler.inl index f6517732..1682b64a 100644 --- a/include/ServerLib/SessionVisibilityHandler.inl +++ b/include/ServerLib/SessionVisibilityHandler.inl @@ -11,6 +11,7 @@ namespace tsom m_controlledCharacter(nullptr), m_networkSession(networkSession) { + m_activeChunkUpdates = std::make_shared(0); } inline void SessionVisibilityHandler::UpdateControlledEntity(entt::handle entity, CharacterController* controller) diff --git a/src/CommonLib/NetworkReactor.cpp b/src/CommonLib/NetworkReactor.cpp index 2c08d024..8bba9165 100644 --- a/src/CommonLib/NetworkReactor.cpp +++ b/src/CommonLib/NetworkReactor.cpp @@ -97,11 +97,12 @@ namespace tsom m_outgoingQueue.enqueue(std::move(outgoingRequest)); } - void NetworkReactor::SendData(std::size_t peerId, Nz::UInt8 channelId, Nz::ENetPacketFlags flags, Nz::NetPacket&& packet) + void NetworkReactor::SendData(std::size_t peerId, Nz::UInt8 channelId, Nz::ENetPacketFlags flags, Nz::NetPacket&& packet, std::function acknowledgeCallback) { assert(peerId >= m_idOffset); OutgoingEvent::PacketEvent packetEvent; + packetEvent.acknowledgeCallback = std::move(acknowledgeCallback); packetEvent.channelId = channelId; packetEvent.packet = std::move(packet); packetEvent.flags = flags; @@ -325,7 +326,13 @@ namespace tsom else if constexpr (std::is_same_v) { if (Nz::ENetPeer* peer = m_clients[outEvent.peerId]) - peer->Send(arg.channelId, arg.flags, std::move(arg.packet)); + { + Nz::ENetPacketRef packet = m_host.AllocatePacket(arg.flags, std::move(arg.packet)); + if (arg.acknowledgeCallback) + packet->OnAcknowledged.Connect(std::move(arg.acknowledgeCallback)); + + peer->Send(arg.channelId, std::move(packet)); + } } else if constexpr (std::is_same_v) { diff --git a/src/ServerLib/SessionVisibilityHandler.cpp b/src/ServerLib/SessionVisibilityHandler.cpp index 8e4acc40..53dcab67 100644 --- a/src/ServerLib/SessionVisibilityHandler.cpp +++ b/src/ServerLib/SessionVisibilityHandler.cpp @@ -104,6 +104,9 @@ namespace tsom for (std::size_t chunkIndex = m_newlyVisibleChunk.FindFirst(); chunkIndex != m_newlyVisibleChunk.npos; chunkIndex = m_newlyVisibleChunk.FindNext(chunkIndex)) { + if (*m_activeChunkUpdates >= MaxConcurrentChunkUpdate) + break; + VisibleChunk& visibleChunk = m_visibleChunks[chunkIndex]; // Connect update signal on dispatch to prevent updates made during the same tick to be sent as update @@ -151,9 +154,15 @@ namespace tsom for (unsigned int i = 0; i < blockCount; ++i) chunkCreatePacket.content[i] = Nz::SafeCast(chunkContent[i]); - m_networkSession->SendPacket(chunkCreatePacket); + (*m_activeChunkUpdates)++; + m_networkSession->SendPacket(chunkCreatePacket, [chunkLocation, chunkUpdateCount = m_activeChunkUpdates] + { + assert(*chunkUpdateCount > 0); + (*chunkUpdateCount)--; + }); + + m_newlyVisibleChunk.UnboundedReset(chunkIndex); } - m_newlyVisibleChunk.Clear(); for (std::size_t chunkIndex = m_updatedChunk.FindFirst(); chunkIndex != m_updatedChunk.npos; chunkIndex = m_updatedChunk.FindNext(chunkIndex)) {