From 2687f2df30210ada485c28c98e52db08d460d5a3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 28 Mar 2021 14:44:20 +0100 Subject: Fix chunk block changes being sent out of order (#5169) * Flush out all pending, buffered changes at the end of each tick, after every chunk is ticked. This makes every block update client-side in unison, instead of unlucky ones only being sent 1 tick later. * Re-add buffer for outgoing network data; IOCP async WSASend has higher overhead than expected... Fixes regression introduced in 054a89dd9 --- src/Chunk.cpp | 88 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 39 deletions(-) (limited to 'src/Chunk.cpp') diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 4aa28d257..5d54f3c16 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -116,6 +116,55 @@ cChunk::~cChunk() +void cChunk::BroadcastPendingChanges(void) +{ + if (const auto PendingBlocksCount = m_PendingSendBlocks.size(); PendingBlocksCount >= 10240) + { + // Resend the full chunk: + for (const auto ClientHandle : m_LoadedByClient) + { + m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::Priority::Medium, ClientHandle); + } + } + else if (PendingBlocksCount == 0) + { + // Only send block entity changes: + for (const auto ClientHandle : m_LoadedByClient) + { + for (const auto BlockEntity : m_PendingSendBlockEntities) + { + BlockEntity->SendTo(*ClientHandle); + } + } + } + else + { + // Send block and block entity changes: + for (const auto ClientHandle : m_LoadedByClient) + { + ClientHandle->SendBlockChanges(m_PosX, m_PosZ, m_PendingSendBlocks); + + for (const auto BlockEntity : m_PendingSendBlockEntities) + { + BlockEntity->SendTo(*ClientHandle); + } + } + } + + // Flush out all buffered data: + for (const auto ClientHandle : m_LoadedByClient) + { + ClientHandle->ProcessProtocolOut(); + } + + m_PendingSendBlocks.clear(); + m_PendingSendBlockEntities.clear(); +} + + + + + void cChunk::SetPresence(cChunk::ePresence a_Presence) { m_Presence = a_Presence; @@ -707,9 +756,6 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt) // Check blocks after everything else to apply at least one round of queued ticks (i.e. cBlockHandler::Check) this tick: CheckBlocks(); - - // Finally, tell the client about all block changes: - BroadcastPendingBlockChanges(); } @@ -771,42 +817,6 @@ void cChunk::MoveEntityToNewChunk(OwnedEntity a_Entity) -void cChunk::BroadcastPendingBlockChanges(void) -{ - if (const auto PendingBlocksCount = m_PendingSendBlocks.size(); PendingBlocksCount >= 10240) - { - // Resend the full chunk: - for (const auto ClientHandle : m_LoadedByClient) - { - m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::Priority::Medium, ClientHandle); - } - } - else if (PendingBlocksCount != 0) - { - // Send block changes: - for (const auto ClientHandle : m_LoadedByClient) - { - ClientHandle->SendBlockChanges(m_PosX, m_PosZ, m_PendingSendBlocks); - } - } - - // Send block entity changes: - for (const auto Entity : m_PendingSendBlockEntities) - { - for (const auto ClientHandle : m_LoadedByClient) - { - Entity->SendTo(*ClientHandle); - } - } - - m_PendingSendBlocks.clear(); - m_PendingSendBlockEntities.clear(); -} - - - - - void cChunk::CheckBlocks() { cChunkInterface ChunkInterface(m_World->GetChunkMap()); -- cgit v1.2.3