summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/cChunk.cpp147
-rw-r--r--source/cChunk.h15
-rw-r--r--source/cClientHandle.cpp71
-rw-r--r--source/cClientHandle.h3
-rw-r--r--source/packets/cPacket_MultiBlock.cpp19
-rw-r--r--source/packets/cPacket_MultiBlock.h24
6 files changed, 155 insertions, 124 deletions
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index 2c97b5955..53c310a2e 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -31,13 +31,6 @@
#include "cPluginManager.h"
#include "blocks/Block.h"
-#include "packets/cPacket_DestroyEntity.h"
-#include "packets/cPacket_PreChunk.h"
-#include "packets/cPacket_BlockChange.h"
-#include "packets/cPacket_MultiBlock.h"
-
-#include "blocks/Block.h"
-
#include <json/json.h>
@@ -358,58 +351,14 @@ void cChunk::Stay(bool a_Stay)
void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
{
- cCSLock Lock(m_CSBlockLists);
- unsigned int PendingSendBlocks = m_PendingSendBlocks.size();
- if( PendingSendBlocks > 1 )
- {
- cPacket_MultiBlock MultiBlock;
- MultiBlock.m_ChunkX = m_PosX;
- MultiBlock.m_ChunkZ = m_PosZ;
- MultiBlock.m_NumBlocks = (short)PendingSendBlocks;
- MultiBlock.m_Data = new cPacket_MultiBlock::sBlockChange[ PendingSendBlocks ];
- MultiBlock.m_DataSize = PendingSendBlocks * sizeof( cPacket_MultiBlock::sBlockChange );
- //LOG("Sending multiblock packet for %i blocks", PendingSendBlocks );
- for( unsigned int i = 0; i < PendingSendBlocks; i++)
- {
- unsigned int index = m_PendingSendBlocks[i];
- Vector3i BlockPos = IndexToCoordinate( index );
-
- unsigned int Coords = BlockPos.y | (BlockPos.z << 8) | (BlockPos.x << 12);
- unsigned int Blocks = GetNibble( m_BlockMeta, index ) | (m_BlockTypes[index] << 4);
- MultiBlock.m_Data[i].Data = Coords << 16 | Blocks;
- }
- m_PendingSendBlocks.clear();
- PendingSendBlocks = m_PendingSendBlocks.size();
- Broadcast( MultiBlock );
- }
- if( PendingSendBlocks > 0 )
- {
- for( unsigned int i = 0; i < PendingSendBlocks; i++)
- {
- unsigned int index = m_PendingSendBlocks[i];
- Vector3i WorldPos = PositionToWorldPosition( IndexToCoordinate( index ) );
-
- cPacket_BlockChange BlockChange;
- BlockChange.m_PosX = WorldPos.x;
- BlockChange.m_PosY = (unsigned char)WorldPos.y;
- BlockChange.m_PosZ = WorldPos.z;
- BlockChange.m_BlockType = m_BlockTypes[index];
- BlockChange.m_BlockMeta = GetNibble( m_BlockMeta, index );
- Broadcast( BlockChange );
- }
- m_PendingSendBlocks.clear();
- }
- Lock.Unlock();
+ BroadcastPendingBlockChanges();
- while ( !m_UnloadQuery.empty() )
+ // Unload the chunk from all clients that have queued unloading:
+ for (cClientHandleList::iterator itr = m_UnloadQuery.begin(), end = m_UnloadQuery.end(); itr != end; ++itr)
{
- cPacket_PreChunk UnloadPacket;
- UnloadPacket.m_PosX = GetPosX();
- UnloadPacket.m_PosZ = GetPosZ();
- UnloadPacket.m_bLoad = false; // Unload
- (*m_UnloadQuery.begin())->Send( UnloadPacket );
- m_UnloadQuery.remove( *m_UnloadQuery.begin() );
+ (*itr)->SendUnloadChunk(m_PosX, m_PosZ);
}
+ m_UnloadQuery.clear();
CheckBlocks();
@@ -429,6 +378,35 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
+void cChunk::BroadcastPendingBlockChanges(void)
+{
+ sSetBlockVector Changes;
+ {
+ cCSLock Lock(m_CSBlockLists);
+ if (m_PendingSendBlocks.empty())
+ {
+ return;
+ }
+ Changes.reserve(m_PendingSendBlocks.size());
+ for (std::vector<unsigned int>::iterator itr = m_PendingSendBlocks.begin(), end = m_PendingSendBlocks.end(); itr != end; ++itr)
+ {
+ unsigned int index = *itr;
+ Vector3i RelPos = IndexToCoordinate(index);
+ Changes.push_back(sSetBlock(m_PosX, m_PosZ, RelPos.x, RelPos.y, RelPos.z, GetBlock(index), GetMeta(index)));
+ } // for itr - m_PendingSendBlocks[]
+ m_PendingSendBlocks.clear();
+ }
+
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(), end = m_LoadedByClient.end(); itr != end; ++itr)
+ {
+ (*itr)->SendBlockChanges(m_PosX, m_PosZ, Changes);
+ }
+}
+
+
+
+
+
void cChunk::CheckBlocks(void)
{
cCSLock Lock2(m_CSBlockLists);
@@ -1176,42 +1154,24 @@ void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, BLO
-void cChunk::SendBlockTo( int a_X, int a_Y, int a_Z, cClientHandle* a_Client )
+void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client)
{
- if( a_Client == 0 )
+ unsigned int index = MakeIndex(a_RelX, a_RelY, a_RelZ);
+ if (index == INDEX_OUT_OF_RANGE)
{
- cCSLock Lock(m_CSBlockLists);
- unsigned int index = MakeIndex( a_X, a_Y, a_Z );
- if( index != INDEX_OUT_OF_RANGE )
- {
- m_PendingSendBlocks.push_back( index );
- }
- else
- {
- LOGWARN("cChunk::SendBlockTo Index out of range!");
- }
+ LOGWARN("cChunk::SendBlockTo Index out of range!");
return;
}
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ if (a_Client == NULL)
{
- if ( *itr == a_Client )
- {
- unsigned int index = MakeIndex( a_X, a_Y, a_Z );
- Vector3i WorldPos = PositionToWorldPosition( a_X, a_Y, a_Z );
- cPacket_BlockChange BlockChange;
- BlockChange.m_PosX = WorldPos.x;
- BlockChange.m_PosY = (unsigned char)WorldPos.y;
- BlockChange.m_PosZ = WorldPos.z;
- if( index != INDEX_OUT_OF_RANGE )
- {
- BlockChange.m_BlockType = m_BlockTypes[ index ];
- BlockChange.m_BlockMeta = GetNibble( m_BlockMeta, index );
- } // else it's both 0
- a_Client->Send( BlockChange );
- break;
- }
+ // Queue the block for all clients in the chunk (will be sent in Tick())
+ m_PendingSendBlocks.push_back(index);
+ return;
}
+
+ Vector3i wp = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
+ a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(index), GetMeta(index));
}
@@ -1362,13 +1322,12 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
m_LoadedByClient.erase(itr);
- if ( !a_Client->IsDestroyed() )
+ if (!a_Client->IsDestroyed())
{
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
{
LOGD("chunk [%i, %i] destroying entity #%i for player \"%s\"", m_PosX, m_PosZ, (*itr)->GetUniqueID(), a_Client->GetUsername().c_str() );
- cPacket_DestroyEntity DestroyEntity( *itr );
- a_Client->Send( DestroyEntity );
+ a_Client->SendDestroyEntity(*(*itr));
}
}
return;
@@ -1982,20 +1941,20 @@ void cChunk::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHa
-void cChunk::PositionToWorldPosition(int a_ChunkX, int a_ChunkY, int a_ChunkZ, int & a_X, int & a_Y, int & a_Z)
+void cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a_BlockX, int & a_BlockY, int & a_BlockZ)
{
- a_Y = a_ChunkY;
- a_X = m_PosX * Width + a_ChunkX;
- a_Z = m_PosZ * Width + a_ChunkZ;
+ a_BlockY = a_RelY;
+ a_BlockX = m_PosX * Width + a_RelX;
+ a_BlockZ = m_PosZ * Width + a_RelZ;
}
-Vector3i cChunk::PositionToWorldPosition( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
+Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ)
{
- return Vector3i( m_PosX * Width + a_ChunkX, m_PosY * Height + a_ChunkY, m_PosZ * Width + a_ChunkZ );
+ return Vector3i(m_PosX * Width + a_RelX, m_PosY * Height + a_RelY, m_PosZ * Width + a_RelZ);
}
diff --git a/source/cChunk.h b/source/cChunk.h
index 707ea5840..1b08f4d6b 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -138,7 +138,7 @@ public:
int GetHeight( int a_X, int a_Z );
- void SendBlockTo( int a_X, int a_Y, int a_Z, cClientHandle* a_Client );
+ void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
/// Adds a client to the chunk; returns true if added, false if already there
bool AddClient (cClientHandle* a_Client );
@@ -193,9 +193,13 @@ public:
void SendBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
- void PositionToWorldPosition(int a_ChunkX, int a_ChunkY, int a_ChunkZ, int & a_X, int & a_Y, int & a_Z);
- Vector3i PositionToWorldPosition( const Vector3i & a_InChunkPos ) { return PositionToWorldPosition( a_InChunkPos.x, a_InChunkPos.y, a_InChunkPos.z ); }
- Vector3i PositionToWorldPosition( int a_ChunkX, int a_ChunkY, int a_ChunkZ );
+ Vector3i PositionToWorldPosition(const Vector3i & a_RelPos)
+ {
+ return PositionToWorldPosition(a_RelPos.x, a_RelPos.y, a_RelPos.z);
+ }
+
+ void PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a_BlockX, int & a_BlockY, int & a_BlockZ);
+ Vector3i PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ );
inline void MarkDirty(void)
{
@@ -268,6 +272,9 @@ private:
// Makes a copy of the list
cClientHandleList GetAllClients(void) const {return m_LoadedByClient; }
+ /// Sends m_PendingSendBlocks to all clients
+ void BroadcastPendingBlockChanges(void);
+
/// Checks the block scheduled for checking in m_ToTickBlocks[]
void CheckBlocks(void);
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index 90672a1ec..a0ec88f80 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -1400,7 +1400,11 @@ void cClientHandle::Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority /* =
if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
{
m_ChunksToSend.erase(itr);
+
+ // TODO: _X: Decouple this from packet sending, it creates a deadlock possibility
+ // -- postpone till Tick() instead, using a bool flag
CheckIfWorldDownloaded();
+
Found = true;
break;
}
@@ -1908,14 +1912,77 @@ void cClientHandle::SendCollectPickup(const cPickup & a_Pickup, const cPlayer &
+void cClientHandle::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+{
+ cPacket_BlockChange BlockChange;
+ BlockChange.m_PosX = a_BlockX;
+ BlockChange.m_PosY = (unsigned char)a_BlockY;
+ BlockChange.m_PosZ = a_BlockZ;
+ BlockChange.m_BlockType = a_BlockType;
+ BlockChange.m_BlockMeta = a_BlockMeta;
+ Send(BlockChange);
+}
+
+
+
+
+
+void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes)
+{
+ if (a_Changes.size() == 1)
+ {
+ // Special packet for single-block changes
+ const sSetBlock & blk = a_Changes.front();
+ SendBlockChange(a_ChunkX * cChunkDef::Width + blk.x, blk.y, a_ChunkZ * cChunkDef::Height + blk.z, blk.BlockType, blk.BlockMeta);
+ return;
+ }
+
+ cPacket_MultiBlock MultiBlock;
+ MultiBlock.m_ChunkX = a_ChunkX;
+ MultiBlock.m_ChunkZ = a_ChunkZ;
+ MultiBlock.m_NumBlocks = (short)a_Changes.size();
+ MultiBlock.m_Data = new cPacket_MultiBlock::sBlockChange[a_Changes.size()];
+ int i = 0;
+ for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr, i++)
+ {
+ unsigned int Coords = itr->y | (itr->z << 8) | (itr->x << 12);
+ unsigned int Blocks = itr->BlockMeta | (itr->BlockType << 4);
+ MultiBlock.m_Data[i].Data = Coords << 16 | Blocks;
+ }
+ Send(MultiBlock);
+}
+
+
+
+
+
+void cClientHandle::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+{
+ cPacket_PreChunk UnloadPacket;
+ UnloadPacket.m_PosX = a_ChunkX;
+ UnloadPacket.m_PosZ = a_ChunkZ;
+ UnloadPacket.m_bLoad = false; // Unload
+ Send(UnloadPacket);
+}
+
+
+
+
+
void cClientHandle::CheckIfWorldDownloaded(void)
{
if (m_State != csDownloadingWorld)
{
return;
}
- cCSLock Lock(m_CSChunkLists);
- if (m_ChunksToSend.empty())
+
+ bool ShouldSendConfirm = false;
+ {
+ cCSLock Lock(m_CSChunkLists);
+ ShouldSendConfirm = m_ChunksToSend.empty();
+ }
+
+ if (ShouldSendConfirm)
{
SendConfirmPosition();
}
diff --git a/source/cClientHandle.h b/source/cClientHandle.h
index 0dc0c2fd9..9c8586ae5 100644
--- a/source/cClientHandle.h
+++ b/source/cClientHandle.h
@@ -114,6 +114,9 @@ public:
void SendSpawnMob (const cMonster & a_Mob);
void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
void SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player);
+ void SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+ void SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes);
+ void SendUnloadChunk(int a_ChunkX, int a_ChunkZ);
const AString & GetUsername(void) const; //tolua_export
diff --git a/source/packets/cPacket_MultiBlock.cpp b/source/packets/cPacket_MultiBlock.cpp
index 9ae175508..68daf2700 100644
--- a/source/packets/cPacket_MultiBlock.cpp
+++ b/source/packets/cPacket_MultiBlock.cpp
@@ -7,15 +7,14 @@
-cPacket_MultiBlock::cPacket_MultiBlock( const cPacket_MultiBlock & a_Copy )
+cPacket_MultiBlock::cPacket_MultiBlock(const cPacket_MultiBlock & a_Copy)
{
- m_PacketID = E_MULTI_BLOCK;
- m_ChunkX = a_Copy.m_ChunkX;
- m_ChunkZ = a_Copy.m_ChunkZ;
+ m_PacketID = E_MULTI_BLOCK;
+ m_ChunkX = a_Copy.m_ChunkX;
+ m_ChunkZ = a_Copy.m_ChunkZ;
m_NumBlocks = a_Copy.m_NumBlocks;
- m_DataSize = a_Copy.m_DataSize;
- m_Data = new sBlockChange[m_NumBlocks];
- memcpy( m_Data, a_Copy.m_Data, sizeof(sBlockChange)*m_NumBlocks );
+ m_Data = new sBlockChange[m_NumBlocks];
+ memcpy(m_Data, a_Copy.m_Data, sizeof(sBlockChange) * m_NumBlocks);
}
@@ -24,7 +23,7 @@ cPacket_MultiBlock::cPacket_MultiBlock( const cPacket_MultiBlock & a_Copy )
cPacket_MultiBlock::~cPacket_MultiBlock()
{
- delete [] m_Data;
+ delete[] m_Data;
}
@@ -38,8 +37,8 @@ void cPacket_MultiBlock::Serialize(AString & a_Data) const
AppendInteger(a_Data, m_ChunkZ);
AppendShort (a_Data, m_NumBlocks);
- AppendInteger(a_Data, m_DataSize);
- for( int i = 0; i < m_NumBlocks; ++i )
+ AppendInteger(a_Data, sizeof(*m_Data) * m_NumBlocks);
+ for (short i = 0; i < m_NumBlocks; ++i)
{
AppendInteger(a_Data, m_Data[i].Data);
}
diff --git a/source/packets/cPacket_MultiBlock.h b/source/packets/cPacket_MultiBlock.h
index af3d24267..7399fe853 100644
--- a/source/packets/cPacket_MultiBlock.h
+++ b/source/packets/cPacket_MultiBlock.h
@@ -12,34 +12,30 @@ class cPacket_MultiBlock : public cPacket
public:
struct sBlockChange
{
- sBlockChange()
- : Data( 0 )
- {}
unsigned int Data;
-// short Data; // 4bits metadata ... 12bits block ID
-// short Coords; // 8bits Y ... 4bits Z ... 4bits X
+ // short Data; // 4bits metadata ... 12bits block ID
+ // short Coords; // 8bits Y ... 4bits Z ... 4bits X
};
cPacket_MultiBlock()
: m_ChunkX( 0 )
, m_ChunkZ( 0 )
, m_NumBlocks( 0 )
- , m_DataSize( 0 )
, m_Data( NULL )
- { m_PacketID = E_MULTI_BLOCK; }
+ {
+ m_PacketID = E_MULTI_BLOCK;
+ }
- cPacket_MultiBlock( const cPacket_MultiBlock & a_Copy );
+ cPacket_MultiBlock(const cPacket_MultiBlock & a_Copy);
~cPacket_MultiBlock();
virtual cPacket* Clone() const { return new cPacket_MultiBlock(*this); }
virtual void Serialize(AString & a_Data) const override;
- int m_ChunkX;
- int m_ChunkZ;
- short m_NumBlocks;
-
- int m_DataSize; // Should be 4 * m_NumBlocks ??
- sBlockChange * m_Data;
+ int m_ChunkX;
+ int m_ChunkZ;
+ short m_NumBlocks;
+ sBlockChange * m_Data; // m_NumBlocks items in the array
};