Skip to content

Commit

Permalink
Stream 4 chunks per tick. Added priority.
Browse files Browse the repository at this point in the history
  • Loading branch information
Howaner committed Oct 6, 2014
1 parent a59f2d1 commit b493beb
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/Chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
}

Expand Down
13 changes: 9 additions & 4 deletions src/ChunkSender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
Expand Down
18 changes: 16 additions & 2 deletions src/ChunkSender.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -84,7 +91,7 @@ class cChunkSender:
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);
Expand All @@ -96,11 +103,13 @@ class cChunkSender:
{
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)
{
}
Expand All @@ -113,6 +122,11 @@ class cChunkSender:
(a_Other.m_Client == m_Client)
);
}

bool operator < (const sSendChunk & a_Other)
{
return (m_Priority < a_Other.m_Priority);
}
} ;
typedef std::list<sSendChunk> sSendChunkList;

Expand Down
35 changes: 22 additions & 13 deletions src/ClientHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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.
Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -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;
}


Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions src/ClientHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "Enchantments.h"
#include "UI/SlotArea.h"
#include "json/json.h"
#include "ChunkSender.h"



Expand Down Expand Up @@ -113,8 +114,8 @@ class cClientHandle : // tolua_export
/** 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);
Expand Down Expand Up @@ -448,7 +449,7 @@ class cClientHandle : // tolua_export
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);
Expand Down
8 changes: 4 additions & 4 deletions src/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down
4 changes: 2 additions & 2 deletions src/World.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,11 @@ class cWorld :

/** 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);
Expand Down

0 comments on commit b493beb

Please sign in to comment.