summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Chunk.cpp2
-rw-r--r--src/ChunkSender.cpp13
-rw-r--r--src/ChunkSender.h18
-rw-r--r--src/ClientHandle.cpp35
-rw-r--r--src/ClientHandle.h7
-rw-r--r--src/World.cpp8
-rw-r--r--src/World.h4
7 files changed, 58 insertions, 29 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 96b8eda4e..e8a1de908 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -1742,7 +1742,7 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max
// Re-send the chunk to all clients:
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
- m_World->ForceSendChunkTo(m_PosX, m_PosZ, (*itr));
+ m_World->ForceSendChunkTo(m_PosX, m_PosZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM, (*itr));
} // for itr - m_LoadedByClient[]
}
diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp
index 0bdc0cf75..2a953db1f 100644
--- a/src/ChunkSender.cpp
+++ b/src/ChunkSender.cpp
@@ -91,17 +91,22 @@ void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkZ)
-void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
+void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client)
{
ASSERT(a_Client != NULL);
{
+ sSendChunk Chunk(a_ChunkX, a_ChunkZ, a_Priority, a_Client);
+
cCSLock Lock(m_CS);
- if (std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, a_ChunkZ, a_Client)) != m_SendChunks.end())
+ if (std::find(m_SendChunks.begin(), m_SendChunks.end(), Chunk) != m_SendChunks.end())
{
// Already queued, bail out
return;
}
- m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkZ, a_Client));
+ m_SendChunks.push_back(Chunk);
+
+ // Sort the list:
+ m_SendChunks.sort();
}
m_evtQueue.Set();
}
@@ -169,7 +174,7 @@ void cChunkSender::Execute(void)
sSendChunk Chunk(m_SendChunks.front());
m_SendChunks.pop_front();
Lock.Unlock();
-
+
SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client);
}
Lock.Lock();
diff --git a/src/ChunkSender.h b/src/ChunkSender.h
index a0e9087a9..3a1e1f5ea 100644
--- a/src/ChunkSender.h
+++ b/src/ChunkSender.h
@@ -75,6 +75,13 @@ class cChunkSender:
public:
cChunkSender(void);
~cChunkSender();
+
+ enum eChunkPriority
+ {
+ E_CHUNK_PRIORITY_HIGH = 0,
+ E_CHUNK_PRIORITY_MEDIUM = 1,
+ E_CHUNK_PRIORITY_LOW = 2,
+ };
bool Start(cWorld * a_World);
@@ -84,7 +91,7 @@ public:
void ChunkReady(int a_ChunkX, int a_ChunkZ);
/// Queues a chunk to be sent to a specific client
- void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
+ void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client);
/// Removes the a_Client from all waiting chunk send operations
void RemoveClient(cClientHandle * a_Client);
@@ -96,11 +103,13 @@ protected:
{
int m_ChunkX;
int m_ChunkZ;
+ eChunkPriority m_Priority;
cClientHandle * m_Client;
- sSendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client) :
+ sSendChunk(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client) :
m_ChunkX(a_ChunkX),
m_ChunkZ(a_ChunkZ),
+ m_Priority(a_Priority),
m_Client(a_Client)
{
}
@@ -113,6 +122,11 @@ protected:
(a_Other.m_Client == m_Client)
);
}
+
+ bool operator < (const sSendChunk & a_Other)
+ {
+ return (m_Priority < a_Other.m_Priority);
+ }
} ;
typedef std::list<sSendChunk> sSendChunkList;
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 535f9d386..588a1caba 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -402,11 +402,11 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID,
-void cClientHandle::StreamNextChunk(void)
+bool cClientHandle::StreamNextChunk(void)
{
if ((m_State < csAuthenticated) || (m_State >= csDestroying))
{
- return;
+ return true;
}
ASSERT(m_Player != NULL);
@@ -415,7 +415,7 @@ void cClientHandle::StreamNextChunk(void)
if ((m_LastStreamedChunkX == ChunkPosX) && (m_LastStreamedChunkZ == ChunkPosZ))
{
// All chunks are already loaded. Abort loading.
- return;
+ return true;
}
// Get the look vector and normalize it.
@@ -454,8 +454,8 @@ void cClientHandle::StreamNextChunk(void)
// Unloaded chunk found -> Send it to the client.
Lock.Unlock();
- StreamChunk(ChunkX, ChunkZ);
- return;
+ StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_HIGH);
+ return false;
}
}
}
@@ -489,8 +489,8 @@ void cClientHandle::StreamNextChunk(void)
// Unloaded chunk found -> Send it to the client.
Lock.Unlock();
- StreamChunk(ChunkX, ChunkZ);
- return;
+ StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_MEDIUM);
+ return false;
}
}
}
@@ -527,14 +527,15 @@ void cClientHandle::StreamNextChunk(void)
// Unloaded chunk found -> Send it to the client.
Lock.Unlock();
- StreamChunk(Coords.m_ChunkX, Coords.m_ChunkZ);
- return;
+ StreamChunk(Coords.m_ChunkX, Coords.m_ChunkZ, cChunkSender::E_CHUNK_PRIORITY_LOW);
+ return false;
}
}
// All chunks are loaded -> Sets the last loaded chunk coordinates to current coordinates
m_LastStreamedChunkX = ChunkPosX;
m_LastStreamedChunkZ = ChunkPosZ;
+ return true;
}
@@ -590,7 +591,7 @@ void cClientHandle::UnloadOutOfRangeChunks(void)
-void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ)
+void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority)
{
if (m_State >= csDestroying)
{
@@ -608,7 +609,7 @@ void cClientHandle::StreamChunk(int a_ChunkX, int a_ChunkZ)
m_LoadedChunks.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, a_ChunkZ));
}
- World->SendChunkTo(a_ChunkX, a_ChunkZ, this);
+ World->SendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, this);
}
}
@@ -2028,8 +2029,16 @@ void cClientHandle::Tick(float a_Dt)
if ((m_State >= csAuthenticated) && (m_State < csDestroying))
{
-
- StreamNextChunk(); // Streams the next chunk
+ // Stream 4 chunks per tick
+ for (int i = 0; i < 4; i++)
+ {
+ // Stream the next chunk
+ if (StreamNextChunk())
+ {
+ // Streaming finished. All chunks are loaded.
+ break;
+ }
+ }
// Unload all chunks that are out of the view distance (all 5 seconds)
if ((m_Player->GetWorld()->GetWorldAge() % 100) == 0)
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index eb91b8487..c6444b1c2 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -21,6 +21,7 @@
#include "Enchantments.h"
#include "UI/SlotArea.h"
#include "json/json.h"
+#include "ChunkSender.h"
@@ -113,8 +114,8 @@ public:
/** Authenticates the specified user, called by cAuthenticator */
void Authenticate(const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties);
- /** This function sends a new unloaded chunk to the player. */
- void StreamNextChunk(void);
+ /** This function sends a new unloaded chunk to the player. Returns true if all chunks are loaded. */
+ bool StreamNextChunk();
/** Remove all loaded chunks that are no longer in range */
void UnloadOutOfRangeChunks(void);
@@ -448,7 +449,7 @@ private:
bool CheckBlockInteractionsRate(void);
/** Adds a single chunk to be streamed to the client; used by StreamChunks() */
- void StreamChunk(int a_ChunkX, int a_ChunkZ);
+ void StreamChunk(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority);
/** Handles the DIG_STARTED dig packet: */
void HandleBlockDigStarted (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta);
diff --git a/src/World.cpp b/src/World.cpp
index 30c1a73b1..049dbc106 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2850,19 +2850,19 @@ void cWorld::RemoveClientFromChunks(cClientHandle * a_Client)
-void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
+void cWorld::SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client)
{
- m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client);
+ m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client);
}
-void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
+void cWorld::ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client)
{
a_Client->AddWantedChunk(a_ChunkX, a_ChunkZ);
- m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Client);
+ m_ChunkSender.QueueSendChunkTo(a_ChunkX, a_ChunkZ, a_Priority, a_Client);
}
diff --git a/src/World.h b/src/World.h
index 90dada259..f940a98c4 100644
--- a/src/World.h
+++ b/src/World.h
@@ -359,11 +359,11 @@ public:
/** Sends the chunk to the client specified, if the client doesn't have the chunk yet.
If chunk not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */
- void SendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
+ void SendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client);
/** Sends the chunk to the client specified, even if the client already has the chunk.
If the chunk's not valid, the request is postponed (ChunkSender will send that chunk when it becomes valid + lighted). */
- void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client);
+ void ForceSendChunkTo(int a_ChunkX, int a_ChunkZ, cChunkSender::eChunkPriority a_Priority, cClientHandle * a_Client);
/** Removes client from ChunkSender's queue of chunks to be sent */
void RemoveClientFromChunkSender(cClientHandle * a_Client);