summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Chunk.cpp2
-rw-r--r--src/ChunkSender.cpp73
-rw-r--r--src/ChunkSender.h11
-rw-r--r--src/ClientHandle.cpp228
-rw-r--r--src/ClientHandle.h11
-rw-r--r--src/Entities/Player.cpp1
-rw-r--r--src/Protocol/Protocol17x.cpp1
-rw-r--r--src/Protocol/Protocol18x.cpp1
-rw-r--r--src/World.cpp9
-rw-r--r--src/World.h6
10 files changed, 226 insertions, 117 deletions
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 7d6d88b26..bfa287f63 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_HIGH, (*itr));
} // for itr - m_LoadedByClient[]
}
diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp
index a3151eb3f..fdcd485a9 100644
--- a/src/ChunkSender.cpp
+++ b/src/ChunkSender.cpp
@@ -91,17 +91,27 @@ 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_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_SendChunksLowPriority.begin(), m_SendChunksLowPriority.end(), Chunk) != m_SendChunksLowPriority.end() ||
+ std::find(m_SendChunksHighPriority.begin(), m_SendChunksHighPriority.end(), Chunk) != m_SendChunksHighPriority.end()
+ )
{
// Already queued, bail out
return;
}
- m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkZ, a_Client));
+
+ if (a_Priority == E_CHUNK_PRIORITY_LOW) {
+ m_SendChunksLowPriority.push_back(Chunk);
+ } else if (a_Priority == E_CHUNK_PRIORITY_HIGH) {
+ m_SendChunksHighPriority.push_back(Chunk);
+ }
}
m_evtQueue.Set();
}
@@ -114,15 +124,24 @@ void cChunkSender::RemoveClient(cClientHandle * a_Client)
{
{
cCSLock Lock(m_CS);
- for (sSendChunkList::iterator itr = m_SendChunks.begin(); itr != m_SendChunks.end();)
+ for (sSendChunkList::iterator itr = m_SendChunksLowPriority.begin(); itr != m_SendChunksLowPriority.end();)
+ {
+ if (itr->m_Client == a_Client)
+ {
+ itr = m_SendChunksLowPriority.erase(itr);
+ continue;
+ }
+ ++itr;
+ } // for itr - m_SendChunksLowPriority[]
+ for (sSendChunkList::iterator itr = m_SendChunksHighPriority.begin(); itr != m_SendChunksHighPriority.end();)
{
if (itr->m_Client == a_Client)
{
- itr = m_SendChunks.erase(itr);
+ itr = m_SendChunksHighPriority.erase(itr);
continue;
}
++itr;
- } // for itr - m_SendChunks[]
+ } // for itr - m_SendChunksHighPriority[]
m_RemoveCount++;
}
m_evtQueue.Set();
@@ -138,7 +157,7 @@ void cChunkSender::Execute(void)
while (!m_ShouldTerminate)
{
cCSLock Lock(m_CS);
- while (m_ChunksReady.empty() && m_SendChunks.empty())
+ while (m_ChunksReady.empty() && m_SendChunksLowPriority.empty() && m_SendChunksHighPriority.empty())
{
int RemoveCount = m_RemoveCount;
m_RemoveCount = 0;
@@ -153,8 +172,17 @@ void cChunkSender::Execute(void)
return;
}
} // while (empty)
-
- if (!m_ChunksReady.empty())
+
+ if (!m_SendChunksHighPriority.empty())
+ {
+ // Take one from the queue:
+ sSendChunk Chunk(m_SendChunksHighPriority.front());
+ m_SendChunksHighPriority.pop_front();
+ Lock.Unlock();
+
+ SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client);
+ }
+ else if (!m_ChunksReady.empty())
{
// Take one from the queue:
cChunkCoords Coords(m_ChunksReady.front());
@@ -166,10 +194,10 @@ void cChunkSender::Execute(void)
else
{
// Take one from the queue:
- sSendChunk Chunk(m_SendChunks.front());
- m_SendChunks.pop_front();
+ sSendChunk Chunk(m_SendChunksLowPriority.front());
+ m_SendChunksLowPriority.pop_front();
Lock.Unlock();
-
+
SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkZ, Chunk.m_Client);
}
Lock.Lock();
@@ -192,40 +220,37 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Clien
ASSERT(m_World != NULL);
// Ask the client if it still wants the chunk:
- if (a_Client != NULL)
+ if ((a_Client != NULL) && !a_Client->WantsSendChunk(a_ChunkX, a_ChunkZ))
{
- if (!a_Client->WantsSendChunk(a_ChunkX, a_ChunkZ))
- {
- return;
- }
+ return;
}
-
+
// If the chunk has no clients, no need to packetize it:
if (!m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ))
{
return;
}
-
+
// If the chunk is not valid, do nothing - whoever needs it has queued it for loading / generating
if (!m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
{
return;
}
-
+
// If the chunk is not lighted, queue it for relighting and get notified when it's ready:
if (!m_World->IsChunkLighted(a_ChunkX, a_ChunkZ))
{
m_World->QueueLightChunk(a_ChunkX, a_ChunkZ, &m_Notify);
return;
}
-
+
// Query and prepare chunk data:
if (!m_World->GetChunkData(a_ChunkX, a_ChunkZ, *this))
{
return;
}
cChunkDataSerializer Data(m_BlockTypes, m_BlockMetas, m_BlockLight, m_BlockSkyLight, m_BiomeMap);
-
+
// Send:
if (a_Client == NULL)
{
@@ -235,7 +260,7 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Clien
{
a_Client->SendChunkData(a_ChunkX, a_ChunkZ, Data);
}
-
+
// Send block-entity packets:
for (sBlockCoords::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
@@ -249,7 +274,7 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Clien
}
} // for itr - m_Packets[]
m_BlockEntities.clear();
-
+
// TODO: Send entity spawn packets
}
diff --git a/src/ChunkSender.h b/src/ChunkSender.h
index a0e9087a9..bd489e2c4 100644
--- a/src/ChunkSender.h
+++ b/src/ChunkSender.h
@@ -75,6 +75,12 @@ class cChunkSender:
public:
cChunkSender(void);
~cChunkSender();
+
+ enum eChunkPriority
+ {
+ E_CHUNK_PRIORITY_HIGH = 0,
+ E_CHUNK_PRIORITY_LOW = 1,
+ };
bool Start(cWorld * a_World);
@@ -84,7 +90,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);
@@ -136,7 +142,8 @@ protected:
cCriticalSection m_CS;
cChunkCoordsList m_ChunksReady;
- sSendChunkList m_SendChunks;
+ sSendChunkList m_SendChunksLowPriority;
+ sSendChunkList m_SendChunksHighPriority;
cEvent m_evtQueue; // Set when anything is added to m_ChunksReady
cEvent m_evtRemoved; // Set when removed clients are safe to be deleted
int m_RemoveCount; // Number of threads waiting for a client removal (m_evtRemoved needs to be set this many times)
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index f15d845ef..ce5056f30 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -405,53 +405,145 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID,
-void cClientHandle::StreamChunks(void)
+bool cClientHandle::StreamNextChunk(void)
{
if ((m_State < csAuthenticated) || (m_State >= csDestroying))
{
- return;
+ return true;
}
-
ASSERT(m_Player != NULL);
- int ChunkPosX = FAST_FLOOR_DIV((int)m_Player->GetPosX(), cChunkDef::Width);
- int ChunkPosZ = FAST_FLOOR_DIV((int)m_Player->GetPosZ(), cChunkDef::Width);
- if ((ChunkPosX == m_LastStreamedChunkX) && (ChunkPosZ == m_LastStreamedChunkZ))
+ int ChunkPosX = m_Player->GetChunkX();
+ int ChunkPosZ = m_Player->GetChunkZ();
+ if ((m_LastStreamedChunkX == ChunkPosX) && (m_LastStreamedChunkZ == ChunkPosZ))
{
- // Already streamed for this position
- return;
+ // All chunks are already loaded. Abort loading.
+ return true;
}
+
+ // Get the look vector and normalize it.
+ Vector3d Position = m_Player->GetEyePosition();
+ Vector3d LookVector = m_Player->GetLookVector();
+ LookVector.Normalize();
+
+ // Lock the list
+ cCSLock Lock(m_CSChunkLists);
+
+ // High priority: Load the chunks that are in the view-direction of the player (with a radius of 3)
+ for (int Range = 0; Range < m_ViewDistance; Range++)
+ {
+ Vector3d Vector = Position + LookVector * cChunkDef::Width * Range;
+
+ // Get the chunk from the x/z coords.
+ int RangeX, RangeZ = 0;
+ cChunkDef::BlockToChunk(FloorC(Vector.x), FloorC(Vector.z), RangeX, RangeZ);
+
+ for (size_t X = 0; X < 7; X++)
+ {
+ for (size_t Z = 0; Z < 7; Z++)
+ {
+ int ChunkX = RangeX + ((X >= 4) ? (3 - X) : X);
+ int ChunkZ = RangeZ + ((Z >= 4) ? (3 - Z) : Z);
+ cChunkCoords Coords(ChunkX, ChunkZ);
+
+ // Checks if the chunk is in distance
+ if ((Diff(ChunkX, ChunkPosX) > m_ViewDistance) || (Diff(ChunkZ, ChunkPosZ) > m_ViewDistance))
+ {
+ continue;
+ }
+
+ // If the chunk already loading/loaded -> skip
+ if (
+ (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) ||
+ (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end())
+ )
+ {
+ continue;
+ }
+
+ // Unloaded chunk found -> Send it to the client.
+ Lock.Unlock();
+ StreamChunk(ChunkX, ChunkZ, cChunkSender::E_CHUNK_PRIORITY_HIGH);
+ return false;
+ }
+ }
+ }
+
+ // Low priority: Add all chunks that are in range. (From the center out to the edge)
+ for (int d = 0; d <= m_ViewDistance; ++d) // cycle through (square) distance, from nearest to furthest
+ {
+ // For each distance add chunks in a hollow square centered around current position:
+ cChunkCoordsList CurcleChunks;
+ for (int i = -d; i <= d; ++i)
+ {
+ CurcleChunks.push_back(cChunkCoords(ChunkPosX + d, ChunkPosZ + i));
+ CurcleChunks.push_back(cChunkCoords(ChunkPosX - d, ChunkPosZ + i));
+ }
+ for (int i = -d + 1; i < d; ++i)
+ {
+ CurcleChunks.push_back(cChunkCoords(ChunkPosX + i, ChunkPosZ + d));
+ CurcleChunks.push_back(cChunkCoords(ChunkPosX + i, ChunkPosZ - d));
+ }
+
+ // For each the CurcleChunks list and send the first unloaded chunk:
+ for (cChunkCoordsList::iterator itr = CurcleChunks.begin(), end = CurcleChunks.end(); itr != end; ++itr)
+ {
+ cChunkCoords Coords = *itr;
+
+ // If the chunk already loading/loaded -> skip
+ if (
+ (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), Coords) != m_ChunksToSend.end()) ||
+ (std::find(m_LoadedChunks.begin(), m_LoadedChunks.end(), Coords) != m_LoadedChunks.end())
+ )
+ {
+ continue;
+ }
+
+ // Unloaded chunk found -> Send it to the client.
+ Lock.Unlock();
+ 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;
-
- LOGD("Streaming chunks centered on [%d, %d], view distance %d", ChunkPosX, ChunkPosZ, m_ViewDistance);
-
- cWorld * World = m_Player->GetWorld();
- ASSERT(World != NULL);
+ return true;
+}
- // Remove all loaded chunks that are no longer in range; deferred to out-of-CS:
- cChunkCoordsList RemoveChunks;
+
+
+
+
+void cClientHandle::UnloadOutOfRangeChunks(void)
+{
+ int ChunkPosX = FAST_FLOOR_DIV((int)m_Player->GetPosX(), cChunkDef::Width);
+ int ChunkPosZ = FAST_FLOOR_DIV((int)m_Player->GetPosZ(), cChunkDef::Width);
+
+ cChunkCoordsList ChunksToRemove;
{
cCSLock Lock(m_CSChunkLists);
for (cChunkCoordsList::iterator itr = m_LoadedChunks.begin(); itr != m_LoadedChunks.end();)
{
- int RelX = (*itr).m_ChunkX - ChunkPosX;
- int RelZ = (*itr).m_ChunkZ - ChunkPosZ;
- if ((RelX > m_ViewDistance) || (RelX < -m_ViewDistance) || (RelZ > m_ViewDistance) || (RelZ < -m_ViewDistance))
+ int DiffX = Diff((*itr).m_ChunkX, ChunkPosX);
+ int DiffZ = Diff((*itr).m_ChunkZ, ChunkPosZ);
+ if ((DiffX > m_ViewDistance) || (DiffZ > m_ViewDistance))
{
- RemoveChunks.push_back(*itr);
+ ChunksToRemove.push_back(*itr);
itr = m_LoadedChunks.erase(itr);
}
else
{
++itr;
}
- } // for itr - m_LoadedChunks[]
+ }
+
for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end();)
{
- int RelX = (*itr).m_ChunkX - ChunkPosX;
- int RelZ = (*itr).m_ChunkZ - ChunkPosZ;
- if ((RelX > m_ViewDistance) || (RelX < -m_ViewDistance) || (RelZ > m_ViewDistance) || (RelZ < -m_ViewDistance))
+ int DiffX = Diff((*itr).m_ChunkX, ChunkPosX);
+ int DiffZ = Diff((*itr).m_ChunkZ, ChunkPosZ);
+ if ((DiffX > m_ViewDistance) || (DiffZ > m_ViewDistance))
{
itr = m_ChunksToSend.erase(itr);
}
@@ -459,52 +551,21 @@ void cClientHandle::StreamChunks(void)
{
++itr;
}
- } // for itr - m_ChunksToSend[]
+ }
}
- for (cChunkCoordsList::iterator itr = RemoveChunks.begin(); itr != RemoveChunks.end(); ++itr)
+
+ for (cChunkCoordsList::iterator itr = ChunksToRemove.begin(); itr != ChunksToRemove.end(); ++itr)
{
- World->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this);
+ m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this);
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
- } // for itr - RemoveChunks[]
-
- // Add all chunks that are in range and not yet in m_LoadedChunks:
- // Queue these smartly - from the center out to the edge
- for (int d = 0; d <= m_ViewDistance; ++d) // cycle through (square) distance, from nearest to furthest
- {
- // For each distance add chunks in a hollow square centered around current position:
- for (int i = -d; i <= d; ++i)
- {
- StreamChunk(ChunkPosX + d, ChunkPosZ + i);
- StreamChunk(ChunkPosX - d, ChunkPosZ + i);
- } // for i
- for (int i = -d + 1; i < d; ++i)
- {
- StreamChunk(ChunkPosX + i, ChunkPosZ + d);
- StreamChunk(ChunkPosX + i, ChunkPosZ - d);
- } // for i
- } // for d
-
- // Touch chunks GENERATEDISTANCE ahead to let them generate:
- for (int d = m_ViewDistance + 1; d <= m_ViewDistance + GENERATEDISTANCE; ++d) // cycle through (square) distance, from nearest to furthest
- {
- // For each distance touch chunks in a hollow square centered around current position:
- for (int i = -d; i <= d; ++i)
- {
- World->TouchChunk(ChunkPosX + d, ChunkPosZ + i);
- World->TouchChunk(ChunkPosX - d, ChunkPosZ + i);
- } // for i
- for (int i = -d + 1; i < d; ++i)
- {
- World->TouchChunk(ChunkPosX + i, ChunkPosZ + d);
- World->TouchChunk(ChunkPosX + i, ChunkPosZ - d);
- } // for i
- } // for d
+ }
}
-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)
{
@@ -522,7 +583,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);
}
}
@@ -545,7 +606,7 @@ void cClientHandle::RemoveFromAllChunks()
m_LoadedChunks.clear();
m_ChunksToSend.clear();
m_SentChunks.clear();
-
+
// Also reset the LastStreamedChunk coords to bogus coords,
// so that all chunks are streamed in subsequent StreamChunks() call (FS #407)
m_LastStreamedChunkX = 0x7fffffff;
@@ -1871,10 +1932,11 @@ void cClientHandle::RemoveFromWorld(void)
{
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
} // for itr - Chunks[]
-
+
// Here, we set last streamed values to bogus ones so everything is resent
m_LastStreamedChunkX = 0x7fffffff;
m_LastStreamedChunkZ = 0x7fffffff;
+
m_HasSentPlayerChunk = false;
}
@@ -1920,7 +1982,7 @@ void cClientHandle::Tick(float a_Dt)
{
return;
}
-
+
// If the chunk the player's in was just sent, spawn the player:
if (m_HasSentPlayerChunk && (m_State == csDownloadingWorld))
{
@@ -1941,6 +2003,26 @@ void cClientHandle::Tick(float a_Dt)
}
}
+ if ((m_State >= csAuthenticated) && (m_State < csDestroying))
+ {
+ // 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)
+ {
+ UnloadOutOfRangeChunks();
+ }
+ }
+
// Handle block break animation:
if (m_BlockDigAnimStage > -1)
{
@@ -1977,7 +2059,7 @@ void cClientHandle::ServerTick(float a_Dt)
if (m_State == csAuthenticated)
{
- StreamChunks();
+ StreamNextChunk();
// Remove the client handle from the server, it will be ticked from its cPlayer object from now on
cRoot::Get()->GetServer()->ClientMovedToWorld(this);
@@ -2765,18 +2847,8 @@ void cClientHandle::SetUsername( const AString & a_Username)
void cClientHandle::SetViewDistance(int a_ViewDistance)
{
- if (a_ViewDistance < MIN_VIEW_DISTANCE)
- {
- a_ViewDistance = MIN_VIEW_DISTANCE;
- }
- if (a_ViewDistance > MAX_VIEW_DISTANCE)
- {
- a_ViewDistance = MAX_VIEW_DISTANCE;
- }
- m_ViewDistance = a_ViewDistance;
-
- // Need to re-stream chunks for the change to become apparent:
- StreamChunks();
+ m_ViewDistance = Clamp(a_ViewDistance, MIN_VIEW_DISTANCE, MAX_VIEW_DISTANCE);
+ LOGD("Setted %s's view distance to %i", GetUsername().c_str(), m_ViewDistance);
}
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 80cf16963..082ed2fcc 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,7 +114,11 @@ public:
/** Authenticates the specified user, called by cAuthenticator */
void Authenticate(const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties);
- void StreamChunks(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);
// Removes the client from all chunks. Used when switching worlds or destroying the player
void RemoveFromAllChunks(void);
@@ -359,7 +364,7 @@ private:
cPlayer * m_Player;
bool m_HasSentDC; ///< True if a D/C packet has been sent in either direction
-
+
// Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk
int m_LastStreamedChunkX;
int m_LastStreamedChunkZ;
@@ -445,7 +450,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/Entities/Player.cpp b/src/Entities/Player.cpp
index 6bd0a3d20..7ead84556 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -235,7 +235,6 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
CanMove = false;
TeleportToCoords(m_LastPos.x, m_LastPos.y, m_LastPos.z);
}
- m_ClientHandle->StreamChunks();
}
if (CanMove)
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 204691ede..9c3bac128 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -1901,6 +1901,7 @@ void cProtocol172::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, ShowCape);
m_Client->SetLocale(Locale);
+ m_Client->SetViewDistance(ViewDistance);
// TODO: Do anything with the other values.
}
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index c9118c239..b6f0618c0 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -2160,6 +2160,7 @@ void cProtocol180::HandlePacketClientSettings(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadChar, char, SkinFlags);
m_Client->SetLocale(Locale);
+ m_Client->SetViewDistance(ViewDistance);
// TODO: Handle other values
}
diff --git a/src/World.cpp b/src/World.cpp
index 1f9361386..1df4c9167 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2857,19 +2857,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);
}
@@ -3498,7 +3498,6 @@ void cWorld::AddQueuedPlayers(void)
cClientHandle * Client = (*itr)->GetClientHandle();
if (Client != NULL)
{
- Client->StreamChunks();
Client->SendPlayerMoveLook();
Client->SendHealth();
Client->SendWholeInventory(*(*itr)->GetWindow());
diff --git a/src/World.h b/src/World.h
index 0ced90562..e9f5b980e 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);