Not sending chunks to the client twice

git-svn-id: http://mc-server.googlecode.com/svn/trunk@399 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
madmaxoft@gmail.com 2012-03-11 10:48:20 +00:00
parent dc8004d5e6
commit af44154ff5
5 changed files with 40 additions and 24 deletions

View File

@ -67,6 +67,8 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cC
ASSERT(a_Client != NULL); ASSERT(a_Client != NULL);
{ {
cCSLock Lock(m_CS); cCSLock Lock(m_CS);
// It should not be already queued:
ASSERT(std::find(m_SendChunks.begin(), m_SendChunks.end(), sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client)) == m_SendChunks.end());
m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client)); m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client));
} }
m_evtQueue.Set(); m_evtQueue.Set();
@ -144,6 +146,15 @@ void cChunkSender::SendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHa
{ {
ASSERT(m_World != NULL); ASSERT(m_World != NULL);
// Ask the client if it still wants the chunk:
if (a_Client != NULL)
{
if (!a_Client->WantsSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ))
{
return;
}
}
// Prepare MapChunk packets: // Prepare MapChunk packets:
if( !m_World->GetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, *this) ) if( !m_World->GetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, *this) )
{ {

View File

@ -77,6 +77,16 @@ protected:
m_Client(a_Client) m_Client(a_Client)
{ {
} }
bool operator ==(const sSendChunk & a_Other)
{
return (
(a_Other.m_ChunkX == m_ChunkX) &&
(a_Other.m_ChunkY == m_ChunkY) &&
(a_Other.m_ChunkZ == m_ChunkZ) &&
(a_Other.m_Client == m_Client)
);
}
}; };
typedef std::list<sSendChunk> sSendChunkList; typedef std::list<sSendChunk> sSendChunkList;

View File

@ -475,27 +475,6 @@ void cClientHandle::RemoveFromAllChunks()
void cClientHandle::ChunkJustSent(cChunk * a_ChunkCompleted)
{
cCSLock Lock(m_CSChunkLists);
for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end(); ++itr)
{
if (((*itr).m_ChunkX == a_ChunkCompleted->GetPosX()) && ((*itr).m_ChunkZ == a_ChunkCompleted->GetPosZ()))
{
m_ChunksToSend.erase(itr);
if ((m_State == csDownloadingWorld) && (m_ChunksToSend.empty()))
{
CheckIfWorldDownloaded();
}
return;
}
} // for itr - m_ChunksToSend[]
}
void cClientHandle::HandlePacket(cPacket * a_Packet) void cClientHandle::HandlePacket(cPacket * a_Packet)
{ {
m_TimeLastPacket = cWorld::GetTime(); m_TimeLastPacket = cWorld::GetTime();
@ -1745,6 +1724,7 @@ void cClientHandle::Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority /* =
int ChunkX = ((cPacket_MapChunk &)a_Packet).m_PosX / cChunk::c_ChunkWidth; int ChunkX = ((cPacket_MapChunk &)a_Packet).m_PosX / cChunk::c_ChunkWidth;
int ChunkZ = ((cPacket_MapChunk &)a_Packet).m_PosZ / cChunk::c_ChunkWidth; int ChunkZ = ((cPacket_MapChunk &)a_Packet).m_PosZ / cChunk::c_ChunkWidth;
#endif #endif
bool Found = false;
cCSLock Lock(m_CSChunkLists); cCSLock Lock(m_CSChunkLists);
for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end(); ++itr) for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end(); ++itr)
{ {
@ -1752,9 +1732,14 @@ void cClientHandle::Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority /* =
{ {
m_ChunksToSend.erase(itr); m_ChunksToSend.erase(itr);
CheckIfWorldDownloaded(); CheckIfWorldDownloaded();
Found = true;
break; break;
} }
} // for itr - m_ChunksToSend[] } // for itr - m_ChunksToSend[]
if (!Found)
{
return;
}
} }
// Optimize away multiple queued RelativeEntityMoveLook packets: // Optimize away multiple queued RelativeEntityMoveLook packets:
@ -1874,6 +1859,16 @@ void cClientHandle::SetViewDistance(int a_ViewDistance)
bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSChunkLists);
return (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)) != m_ChunksToSend.end());
}
void cClientHandle::DataReceived(const char * a_Data, int a_Size) void cClientHandle::DataReceived(const char * a_Data, int a_Size)
{ {
// Data is received from the client // Data is received from the client

View File

@ -86,8 +86,6 @@ public:
// Removes the client from all chunks. Used when switching worlds or destroying the player // Removes the client from all chunks. Used when switching worlds or destroying the player
void RemoveFromAllChunks(void); void RemoveFromAllChunks(void);
void ChunkJustSent(cChunk * a_ChunkSent); // Called by cChunk when it is loaded / generated and sent to all clients registered in it
inline bool IsLoggedIn(void) const { return m_State >= csAuthenticating; } inline bool IsLoggedIn(void) const { return m_State >= csAuthenticating; }
void Tick(float a_Dt); void Tick(float a_Dt);
@ -106,6 +104,9 @@ public:
void SetViewDistance(int a_ViewDistance); //tolua_export void SetViewDistance(int a_ViewDistance); //tolua_export
int GetUniqueID() const { return m_UniqueID; } //tolua_export int GetUniqueID() const { return m_UniqueID; } //tolua_export
/// Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend)
bool WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
private: private:

View File

@ -168,7 +168,6 @@ cPacket_MapChunk::cPacket_MapChunk( const cPacket_MapChunk & a_Copy )
void cPacket_MapChunk::Serialize(AString & a_Data) const void cPacket_MapChunk::Serialize(AString & a_Data) const
{ {
LOG("Sending chunk [%i, %i]", m_PosX, m_PosZ );
AppendByte (a_Data, m_PacketID); AppendByte (a_Data, m_PacketID);
#if (MINECRAFT_1_2_2 == 1 ) #if (MINECRAFT_1_2_2 == 1 )