1
0
Fork 0

Stream 4 chunks per tick. Added priority.

This commit is contained in:
Howaner 2014-10-06 21:27:53 +02:00
parent a59f2d15fb
commit b493beb3bb
7 changed files with 58 additions and 29 deletions

View File

@ -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[]
}

View File

@ -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();

View File

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

View File

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

View File

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

View File

@ -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);
}

View File

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