summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--VC2008/MCServer.vcproj10
-rw-r--r--VC2010/MCServer.vcxproj2
-rw-r--r--VC2010/MCServer.vcxproj.filters2
-rw-r--r--source/ChunkSender.cpp133
-rw-r--r--source/ChunkSender.h63
-rw-r--r--source/Globals.h9
-rw-r--r--source/cBlockEntity.h30
-rw-r--r--source/cChunk.cpp115
-rw-r--r--source/cChunk.h15
-rw-r--r--source/cChunk.inl.h46
-rw-r--r--source/cChunkMap.cpp51
-rw-r--r--source/cChunkMap.h9
-rw-r--r--source/cClientHandle.cpp55
-rw-r--r--source/cClientHandle.h2
-rw-r--r--source/cPlayer.cpp8
-rw-r--r--source/cSignEntity.cpp28
-rw-r--r--source/cSignEntity.h3
-rw-r--r--source/cWorld.cpp22
-rw-r--r--source/cWorld.h12
-rw-r--r--source/packets/cPacket_MapChunk.cpp68
-rw-r--r--source/packets/cPacket_MapChunk.h13
21 files changed, 466 insertions, 230 deletions
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index 0d2168c6e..c647ec267 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -42,7 +42,7 @@
AdditionalOptions="/MP"
Optimization="0"
AdditionalIncludeDirectories="../zlib-1.2.5;../jsoncpp-src-0.5.0/include;../lua-5.1.4/src;../tolua++-1.0.93/include"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;MINECRAFT_1_2_2=1"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -290,6 +290,14 @@
>
</File>
<File
+ RelativePath="..\source\ChunkSender.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\source\ChunkSender.h"
+ >
+ </File>
+ <File
RelativePath="..\source\cInventory.cpp"
>
</File>
diff --git a/VC2010/MCServer.vcxproj b/VC2010/MCServer.vcxproj
index aece29df4..89662dba8 100644
--- a/VC2010/MCServer.vcxproj
+++ b/VC2010/MCServer.vcxproj
@@ -329,6 +329,7 @@
<ClCompile Include="..\Source\cGroup.cpp" />
<ClCompile Include="..\Source\cGroupManager.cpp" />
<ClCompile Include="..\Source\cHeartBeat.cpp" />
+ <ClCompile Include="..\source\ChunkSender.cpp" />
<ClCompile Include="..\source\cIsThread.cpp" />
<ClCompile Include="..\source\cItem.cpp" />
<ClCompile Include="..\source\cLavaSimulator.cpp" />
@@ -513,6 +514,7 @@
<ClInclude Include="..\Source\cGroup.h" />
<ClInclude Include="..\Source\cGroupManager.h" />
<ClInclude Include="..\Source\cHeartBeat.h" />
+ <ClInclude Include="..\source\ChunkSender.h" />
<ClInclude Include="..\source\cIsThread.h" />
<ClInclude Include="..\Source\cLadder.h" />
<ClInclude Include="..\source\cLavaSimulator.h" />
diff --git a/VC2010/MCServer.vcxproj.filters b/VC2010/MCServer.vcxproj.filters
index 76d6862fe..4640ff5de 100644
--- a/VC2010/MCServer.vcxproj.filters
+++ b/VC2010/MCServer.vcxproj.filters
@@ -918,6 +918,7 @@
<ClCompile Include="..\source\cRedstoneSimulator.cpp">
<Filter>Simulator\cSimulator\cRedstoneSimulator</Filter>
</ClCompile>
+ <ClCompile Include="..\source\ChunkSender.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\source\cServer.h">
@@ -1417,6 +1418,7 @@
<ClInclude Include="..\source\cRedstoneSimulator.h">
<Filter>Simulator\cSimulator\cRedstoneSimulator</Filter>
</ClInclude>
+ <ClInclude Include="..\source\ChunkSender.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\source\AllToLua.pkg">
diff --git a/source/ChunkSender.cpp b/source/ChunkSender.cpp
new file mode 100644
index 000000000..527db4543
--- /dev/null
+++ b/source/ChunkSender.cpp
@@ -0,0 +1,133 @@
+
+// ChunkSender.cpp
+
+// Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients
+
+
+
+
+
+#include "Globals.h"
+#include "ChunkSender.h"
+#include "cWorld.h"
+#include "packets/cPacket_MapChunk.h"
+#include "packets/cPacket_PreChunk.h"
+#include "cBlockEntity.h"
+
+
+
+
+
+cChunkSender::cChunkSender(void) :
+ super("ChunkSender"),
+ m_World(NULL)
+{
+}
+
+
+
+
+
+cChunkSender::~cChunkSender()
+{
+ mShouldTerminate = true;
+ m_Event.Set();
+}
+
+
+
+
+
+bool cChunkSender::Start(cWorld * a_World)
+{
+ m_World = a_World;
+ return super::Start();
+}
+
+
+
+
+
+void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+{
+ // This is probably never gonna be called twice for the same chunk, and if it is, we don't mind, so we don't check
+ {
+ cCSLock Lock(m_CS);
+ m_ChunksReady.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ }
+ m_Event.Set();
+}
+
+
+
+
+
+void cChunkSender::Execute(void)
+{
+ while (!mShouldTerminate)
+ {
+ cCSLock Lock(m_CS);
+ while (m_ChunksReady.empty())
+ {
+ cCSUnlock Unlock(Lock);
+ m_Event.Wait();
+ if (mShouldTerminate)
+ {
+ return;
+ }
+ } // while (empty)
+
+ // Take one from the queue:
+ cChunkCoords Coords(m_ChunksReady.front());
+ m_ChunksReady.pop_front();
+ Lock.Unlock();
+
+ ASSERT(m_World != NULL);
+
+ // Send it to anyone waiting:
+ m_World->GetChunkData(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, this);
+ cPacket_PreChunk PreChunk(Coords.m_ChunkX, Coords.m_ChunkZ, true);
+ cPacket_MapChunk MapChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, m_BlockData);
+ m_World->BroadcastToChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, PreChunk);
+ m_World->BroadcastToChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, MapChunk);
+
+ // Send entity creation packets:
+ for (PacketList::iterator itr = m_Packets.begin(); itr != m_Packets.end(); ++itr)
+ {
+ m_World->BroadcastToChunk(Coords.m_ChunkX, Coords.m_ChunkY, Coords.m_ChunkZ, **itr);
+ delete *itr;
+ } // for itr - m_Packets
+ m_Packets.clear();
+
+ } // while (!mShouldTerminate)
+}
+
+
+
+
+
+void cChunkSender::BlockData(const char * a_Data)
+{
+ memcpy(m_BlockData, a_Data, cChunk::c_BlockDataSize);
+}
+
+
+
+
+
+void cChunkSender::BlockEntity(cBlockEntity * a_Entity)
+{
+ m_Packets.push_back(a_Entity->GetPacket());
+}
+
+
+
+
+void cChunkSender::Entity(cEntity * a_Entity)
+{
+ // Nothing needed yet, perhaps in the future when we save entities into chunks we'd like to send them upon load, too ;)
+}
+
+
+
+
diff --git a/source/ChunkSender.h b/source/ChunkSender.h
new file mode 100644
index 000000000..a56e797da
--- /dev/null
+++ b/source/ChunkSender.h
@@ -0,0 +1,63 @@
+
+// ChunkSender.h
+
+// Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients
+
+
+
+
+
+#pragma once
+
+#include "cIsThread.h"
+#include "cChunk.h"
+#include "packets/cPacket.h"
+
+
+
+
+
+class cWorld;
+
+
+
+
+
+class cChunkSender:
+ public cIsThread,
+ public cChunkDataCallback
+{
+ typedef cIsThread super;
+public:
+ cChunkSender(void);
+ ~cChunkSender();
+
+ bool Start(cWorld * a_World);
+
+ void ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+
+protected:
+
+ cWorld * m_World;
+
+ cCriticalSection m_CS;
+ cChunkCoordsList m_ChunksReady;
+ cEvent m_Event; // Set when anything is added to m_ChunksReady
+
+ // Data about the chunk that is being sent:
+ char m_BlockData[cChunk::c_BlockDataSize];
+ PacketList m_Packets; // Accumulator for the entity-packets to send
+
+ // cIsThread override:
+ virtual void Execute(void) override;
+
+ // cChunkDataCallback overrides:
+ virtual void BlockData(const char * a_Data) override;
+ virtual void Entity(cEntity * a_Entity) override;
+ virtual void BlockEntity(cBlockEntity * a_Entity) override;
+
+} ;
+
+
+
+
diff --git a/source/Globals.h b/source/Globals.h
index ce122528c..419d5f5a7 100644
--- a/source/Globals.h
+++ b/source/Globals.h
@@ -144,4 +144,11 @@ public:
-#define MINECRAFT_1_2_2 (1) \ No newline at end of file
+// TODO: Remove this when 1.2 is the major version out there and we're fully compatible
+#ifndef MINECRAFT_1_2_2
+ #define MINECRAFT_1_2_2 (1)
+#endif
+
+
+
+
diff --git a/source/cBlockEntity.h b/source/cBlockEntity.h
index ad1cf14ba..ab0a6c6ca 100644
--- a/source/cBlockEntity.h
+++ b/source/cBlockEntity.h
@@ -1,6 +1,13 @@
#pragma once
+#include "cClientHandle.h"
+#include "cWorld.h"
+
+
+
+
+
#ifndef _WIN32
#include "BlockID.h"
#else
@@ -16,9 +23,9 @@ namespace Json
class Value;
};
-class cClientHandle;
class cPlayer;
class cWorld;
+class cPacket;
@@ -49,7 +56,26 @@ public:
virtual void SaveToJson (Json::Value & a_Value ) = 0;
virtual void UsedBy( cPlayer * a_Player ) = 0;
- virtual void SendTo( cClientHandle* a_Client ) { (void)a_Client; }
+
+ void SendTo( cClientHandle* a_Client )
+ {
+ std::auto_ptr<cPacket> Packet(GetPacket());
+ if (Packet.get() == NULL)
+ {
+ return;
+ }
+ if ( a_Client != NULL )
+ {
+ a_Client->Send(Packet.get());
+ }
+ else // broadcast to all chunk clients
+ {
+ m_World->BroadcastToChunkOfBlock(m_PosX, m_PosY, m_PosZ, Packet.get());
+ }
+ }
+
+ /// Returns the packet to send to clients to represent this entity; NULL if no packet needed; caller is supposed to delete the packet
+ virtual cPacket * GetPacket(void) {return NULL; }
protected:
int m_PosX; // Position in block coordinates
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index fc26b380d..48d2bc086 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -294,6 +294,16 @@ void cChunk::GetBlocks(char * a_Blocks)
+/// Copies m_BlockData into a_Blocks, only the block types
+void cChunk::GetBlockData(char * a_BlockData)
+{
+ memcpy(a_BlockData, m_BlockData, cChunk::c_BlockDataSize);
+}
+
+
+
+
+
/// Returns true if there is a block entity at the coords specified
bool cChunk::HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ)
{
@@ -359,13 +369,13 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
#if (MINECRAFT_1_2_2 == 1)
unsigned int Coords = Y | Z << 8 | X << 12;
- unsigned int Blocks = GetLight( m_BlockMeta, index ) | (m_BlockType[index]<<4);
+ unsigned int Blocks = GetNibble( m_BlockMeta, index ) | (m_BlockType[index]<<4);
MultiBlock.m_Data[i].Data = Coords << 16 | Blocks;
#else
MultiBlock.m_BlockCoordinates[i] = (Z&0xf) | (X&0xf)<<4 | (Y&0xff)<<8;
//LOG("X: %i Y: %i Z: %i Combo: 0x%04x", X, Y, Z, MultiBlock.m_BlockCoordinates[i] );
MultiBlock.m_BlockTypes[i] = m_BlockType[index];
- MultiBlock.m_BlockMetas[i] = GetLight( m_BlockMeta, index );
+ MultiBlock.m_BlockMetas[i] = GetNibble( m_BlockMeta, index );
#endif
}
m_PendingSendBlocks.clear();
@@ -386,7 +396,7 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
BlockChange.m_PosY = (char)(Y + m_PosY*c_ChunkHeight);
BlockChange.m_PosZ = Z + m_PosZ*c_ChunkWidth;
BlockChange.m_BlockType = m_BlockType[index];
- BlockChange.m_BlockMeta = GetLight( m_BlockMeta, index );
+ BlockChange.m_BlockMeta = GetNibble( m_BlockMeta, index );
Broadcast( BlockChange );
}
m_PendingSendBlocks.clear();
@@ -466,7 +476,7 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
isRedstone = true;
case E_BLOCK_TORCH:
{
- char Dir = cTorch::MetaDataToDirection( GetLight( m_BlockMeta, X, Y, Z ) );
+ char Dir = cTorch::MetaDataToDirection( GetNibble( m_BlockMeta, X, Y, Z ) );
LOG("MetaData: %i", Dir );
int XX = X + m_PosX*c_ChunkWidth;
int YY = Y + m_PosY*c_ChunkHeight;
@@ -490,7 +500,7 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
break;
case E_BLOCK_LADDER:
{
- char Dir = cLadder::MetaDataToDirection( GetLight( m_BlockMeta, X, Y, Z ) );
+ char Dir = cLadder::MetaDataToDirection( GetNibble( m_BlockMeta, X, Y, Z ) );
int XX = X + m_PosX*c_ChunkWidth;
int YY = Y + m_PosY*c_ChunkHeight;
int ZZ = Z + m_PosZ*c_ChunkWidth;
@@ -534,13 +544,13 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
case E_BLOCK_DIRT:
{
char AboveBlock = GetBlock( Index+1 );
- if ( (AboveBlock == 0) && GetLight( m_BlockSkyLight, Index ) > 0xf/2 ) // Half lit //changed to not allow grass if any one hit object is on top
+ if ( (AboveBlock == 0) && GetNibble( m_BlockSkyLight, Index ) > 0xf/2 ) // Half lit //changed to not allow grass if any one hit object is on top
{
- FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_GRASS, GetLight( m_BlockMeta, Index ) );
+ FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_GRASS, GetNibble( m_BlockMeta, Index ) );
}
- if ( (g_BlockOneHitDig[AboveBlock]) && GetLight( m_BlockSkyLight, Index+1 ) > 0xf/2 ) // Half lit //ch$
+ if ( (g_BlockOneHitDig[AboveBlock]) && GetNibble( m_BlockSkyLight, Index+1 ) > 0xf/2 ) // Half lit //ch$
{
- FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_GRASS, GetLight( m_BlockMeta, Index ) );
+ FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_GRASS, GetNibble( m_BlockMeta, Index ) );
}
break;
@@ -552,13 +562,13 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
char AboveBlock = GetBlock( Index+1 );
if (!( (AboveBlock == 0) || (g_BlockOneHitDig[AboveBlock]) || (g_BlockTransparent[AboveBlock]) ) ) //changed to not allow grass if any one hit object is on top
{
- FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_DIRT, GetLight( m_BlockMeta, Index ) );
+ FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_DIRT, GetNibble( m_BlockMeta, Index ) );
}
}
break;
case E_BLOCK_SAPLING: //todo: check meta of sapling. change m_World->GrowTree to look change trunk and leaves based on meta of sapling
{
- FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_AIR, GetLight( m_BlockMeta, Index ) );
+ FastSetBlock( m_BlockTickX, m_BlockTickY, m_BlockTickZ, E_BLOCK_AIR, GetNibble( m_BlockMeta, Index ) );
m_World->GrowTree( m_BlockTickX + m_PosX*c_ChunkWidth, m_BlockTickY, m_BlockTickZ + m_PosZ*c_ChunkWidth );
}
break;
@@ -675,12 +685,12 @@ void cChunk::CalculateLighting()
{
// Calculate sunlight
memset(m_BlockSkyLight, 0xff, c_NumBlocks / 2 ); // Set all to fully lit, so everything above HeightMap is lit
- for(int x = 0; x < c_ChunkWidth; x++)
+ for (int x = 0; x < c_ChunkWidth; x++)
{
- for(int z = 0; z < c_ChunkWidth; z++)
+ for (int z = 0; z < c_ChunkWidth; z++)
{
char sunlight = 0xf;
- for(int y = m_HeightMap[x + z*c_ChunkWidth]; y > -1; y--)
+ for (int y = m_HeightMap[x + z*c_ChunkWidth]; y > -1; y--)
{
int index = y + (z * c_ChunkHeight) + (x * c_ChunkHeight * c_ChunkWidth);
@@ -688,21 +698,21 @@ void cChunk::CalculateLighting()
{
sunlight = 0x0;
}
- SetLight( m_BlockSkyLight, x, y, z, sunlight );
+ SetNibble( m_BlockSkyLight, x, y, z, sunlight );
}
}
}
// Calculate blocklights
- for(int x = 0; x < c_ChunkWidth; x++)
+ for (int x = 0; x < c_ChunkWidth; x++)
{
- for(int z = 0; z < c_ChunkWidth; z++)
+ for (int z = 0; z < c_ChunkWidth; z++)
{
int MaxHeight = m_HeightMap[x + z*c_ChunkWidth];
- for(int y = 0; y < MaxHeight; y++)
+ for (int y = 0; y < MaxHeight; y++)
{
char BlockID = GetBlock(x, y, z);
- SetLight( m_BlockLight, x, y, z, g_BlockLightValue[(int)BlockID] );
+ SetNibble( m_BlockLight, x, y, z, g_BlockLightValue[(int)BlockID] );
}
}
}
@@ -710,6 +720,8 @@ void cChunk::CalculateLighting()
SpreadLight(m_BlockSkyLight);
SpreadLight(m_BlockLight);
+ MarkDirty();
+
// Stop it from calculating again :P
m_bCalculateLighting = false;
}
@@ -762,11 +774,11 @@ void cChunk::SpreadLight(char* a_LightBuffer)
int index = y + (z * c_ChunkHeight) + (0 * c_ChunkHeight * c_ChunkWidth);
if( g_BlockSpreadLightFalloff[ m_BlockData[index] ] > 0 )
{
- char CurrentLight = GetLight( a_LightBuffer, 0, y, z );
- char LeftLight = GetLight( LeftSky, c_ChunkWidth-1, y, z );
+ char CurrentLight = GetNibble( a_LightBuffer, 0, y, z );
+ char LeftLight = GetNibble( LeftSky, c_ChunkWidth-1, y, z );
if( LeftLight < CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ] )
{
- SetLight( LeftSky, c_ChunkWidth-1, y, z, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
+ SetNibble( LeftSky, c_ChunkWidth - 1, y, z, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
bCalcLeft = true;
}
}
@@ -776,11 +788,11 @@ void cChunk::SpreadLight(char* a_LightBuffer)
int index = y + (z * c_ChunkHeight) + ((c_ChunkWidth-1) * c_ChunkHeight * c_ChunkWidth);
if( g_BlockSpreadLightFalloff[ m_BlockData[index] ] > 0 )
{
- char CurrentLight = GetLight( a_LightBuffer, c_ChunkWidth-1, y, z );
- char RightLight = GetLight( RightSky, 0, y, z );
+ char CurrentLight = GetNibble( a_LightBuffer, c_ChunkWidth-1, y, z );
+ char RightLight = GetNibble( RightSky, 0, y, z );
if( RightLight < CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ] )
{
- SetLight( RightSky, 0, y, z, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
+ SetNibble( RightSky, 0, y, z, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
bCalcRight = true;
}
}
@@ -806,11 +818,11 @@ void cChunk::SpreadLight(char* a_LightBuffer)
int index = y + (0 * c_ChunkHeight) + (x * c_ChunkHeight * c_ChunkWidth);
if( g_BlockSpreadLightFalloff[ m_BlockData[index] ] > 0 )
{
- char CurrentLight = GetLight( a_LightBuffer, x, y, 0 );
- char FrontLight = GetLight( FrontSky, x, y, c_ChunkWidth-1 );
+ char CurrentLight = GetNibble( a_LightBuffer, x, y, 0 );
+ char FrontLight = GetNibble( FrontSky, x, y, c_ChunkWidth-1 );
if( FrontLight < CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ] )
{
- SetLight( FrontSky, x, y, c_ChunkWidth-1, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
+ SetNibble( FrontSky, x, y, c_ChunkWidth-1, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
bCalcFront = true;
}
}
@@ -820,41 +832,22 @@ void cChunk::SpreadLight(char* a_LightBuffer)
int index = y + ((c_ChunkWidth-1) * c_ChunkHeight) + (x * c_ChunkHeight * c_ChunkWidth);
if( g_BlockSpreadLightFalloff[ m_BlockData[index] ] > 0 )
{
- char CurrentLight = GetLight( a_LightBuffer, x, y, c_ChunkWidth-1 );
- char BackLight = GetLight( BackSky, x, y, 0 );
+ char CurrentLight = GetNibble( a_LightBuffer, x, y, c_ChunkWidth-1 );
+ char BackLight = GetNibble( BackSky, x, y, 0 );
if ( BackLight < CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ] )
{
- SetLight( BackSky, x, y, 0, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
+ SetNibble( BackSky, x, y, 0, MAX(0, CurrentLight-g_BlockSpreadLightFalloff[ m_BlockData[index] ]) );
bCalcBack = true;
}
}
}
}
- if( bCalcLeft ) m_World->ReSpreadLighting( m_PosX - 1, m_PosY, m_PosZ );
- if( bCalcRight ) m_World->ReSpreadLighting( m_PosX + 1, m_PosY, m_PosZ );
- if( bCalcFront ) m_World->ReSpreadLighting( m_PosX, m_PosY, m_PosZ - 1 );
- if( bCalcBack ) m_World->ReSpreadLighting( m_PosX, m_PosY, m_PosZ + 1 );
-}
-
-
-
-
-
-void cChunk::SendTo(cClientHandle* a_Client)
-{
- cPacket_PreChunk PreChunk;
- PreChunk.m_PosX = m_PosX;
- PreChunk.m_PosZ = m_PosZ;
- PreChunk.m_bLoad = true;
- a_Client->Send( PreChunk );
- a_Client->Send( cPacket_MapChunk( this ) );
-
- cCSLock Lock(m_CSBlockLists);
- for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr )
- {
- (*itr)->SendTo( a_Client );
- }
+ if ( bCalcLeft ) m_World->ReSpreadLighting( m_PosX - 1, m_PosY, m_PosZ );
+ if ( bCalcRight ) m_World->ReSpreadLighting( m_PosX + 1, m_PosY, m_PosZ );
+ if ( bCalcFront ) m_World->ReSpreadLighting( m_PosX, m_PosY, m_PosZ - 1 );
+ if ( bCalcBack ) m_World->ReSpreadLighting( m_PosX, m_PosY, m_PosZ + 1 );
+ // No need to set those neighbors dirty, they will recalc their light anyway so they'll get marked dirty there
}
@@ -871,12 +864,11 @@ void cChunk::SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_Block
ASSERT(IsValid()); // Is this chunk loaded / generated?
int index = a_Y + (a_Z * c_ChunkHeight) + (a_X * c_ChunkHeight * c_ChunkWidth);
- char OldBlockMeta = GetLight( m_BlockMeta, index );
+ char OldBlockMeta = GetNibble( m_BlockMeta, index );
char OldBlockType = m_BlockType[index];
m_BlockType[index] = a_BlockType;
- // It's called SetLight(), but it sets the Meta when passed the BlockMeta workspace
- SetLight( m_BlockMeta, index, a_BlockMeta );
+ SetNibble( m_BlockMeta, index, a_BlockMeta );
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
{
@@ -968,7 +960,7 @@ void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_B
const int index = a_Y + (a_Z * c_ChunkHeight) + (a_X * c_ChunkHeight * c_ChunkWidth);
const char OldBlock = m_BlockType[index];
- const char OldBlockMeta = GetLight( m_BlockMeta, index );
+ const char OldBlockMeta = GetNibble( m_BlockMeta, index );
if (OldBlock == a_BlockType && OldBlockMeta == a_BlockMeta)
{
return;
@@ -983,8 +975,7 @@ void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_B
m_PendingSendBlocks.push_back( index );
}
- // It's called SetLight(), but it sets the Meta when passed the BlockMeta workspace
- SetLight( m_BlockMeta, index, a_BlockMeta );
+ SetNibble( m_BlockMeta, index, a_BlockMeta );
// ONLY recalculate lighting if it's necessary!
if(
@@ -1046,7 +1037,7 @@ void cChunk::SendBlockTo( int a_X, int a_Y, int a_Z, cClientHandle* a_Client )
if( index != INDEX_OUT_OF_RANGE )
{
BlockChange.m_BlockType = m_BlockType[ index ];
- BlockChange.m_BlockMeta = GetLight( m_BlockMeta, index );
+ BlockChange.m_BlockMeta = GetNibble( m_BlockMeta, index );
} // else it's both 0
a_Client->Send( BlockChange );
break;
diff --git a/source/cChunk.h b/source/cChunk.h
index dfbbd0c98..aad652c40 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -145,7 +145,10 @@ public:
void SetAllData(const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
/// Copies m_BlockData into a_Blocks, only the block types
- void GetBlocks(char a_Blocks[cChunk::c_NumBlocks]);
+ void GetBlocks(char * a_Blocks);
+
+ /// Copies m_BlockData into a_Blocks, the entire array
+ void GetBlockData(char * a_BlockData);
/// Returns true if there is a block entity at the coords specified
bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ);
@@ -160,7 +163,7 @@ public:
int GetPosZ() { return m_PosZ; }
cWorld * GetWorld() { return m_World; }
- void SendTo( cClientHandle * a_Client );
+ // OBSOLETE void SendTo( cClientHandle * a_Client );
void SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta );
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, char a_BlockType, char a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
@@ -206,10 +209,10 @@ public:
void CopyBlockDataFrom(const char * a_NewBlockData); // Copies all blockdata, recalculates heightmap (used by chunk loaders)
- char GetLight(char* a_Buffer, int a_BlockIdx);
- char GetLight(char* a_Buffer, int x, int y, int z);
- void SetLight(char* a_Buffer, int a_BlockIdx, char a_Light);
- void SetLight(char* a_Buffer, int x, int y, int z, char light);
+ static char GetNibble(char * a_Buffer, int a_BlockIdx);
+ static char GetNibble(char * a_Buffer, int x, int y, int z);
+ static void SetNibble(char * a_Buffer, int a_BlockIdx, char a_Light);
+ static void SetNibble(char * a_Buffer, int x, int y, int z, char light);
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 );
diff --git a/source/cChunk.inl.h b/source/cChunk.inl.h
index 36643a87c..16d1855dd 100644
--- a/source/cChunk.inl.h
+++ b/source/cChunk.inl.h
@@ -11,7 +11,7 @@
__C_CHUNK_INLINE__
-char cChunk::GetLight(char* a_Buffer, int a_BlockIdx)
+char cChunk::GetNibble(char* a_Buffer, int a_BlockIdx)
{
if( a_BlockIdx > -1 && a_BlockIdx < c_NumBlocks )
{
@@ -33,7 +33,7 @@ char cChunk::GetLight(char* a_Buffer, int a_BlockIdx)
__C_CHUNK_INLINE__
-char cChunk::GetLight(char* a_Buffer, int x, int y, int z)
+char cChunk::GetNibble(char* a_Buffer, int x, int y, int z)
{
if( x < c_ChunkWidth && x > -1 && y < c_ChunkHeight && y > -1 && z < c_ChunkWidth && z > -1 )
{
@@ -55,7 +55,7 @@ char cChunk::GetLight(char* a_Buffer, int x, int y, int z)
__C_CHUNK_INLINE__
-void cChunk::SetLight(char* a_Buffer, int a_BlockIdx, char a_Light)
+void cChunk::SetNibble(char* a_Buffer, int a_BlockIdx, char a_Light)
{
if( a_BlockIdx > -1 && a_BlockIdx < c_NumBlocks )
{
@@ -70,7 +70,6 @@ void cChunk::SetLight(char* a_Buffer, int a_BlockIdx, char a_Light)
a_Buffer[cindex] &= 0x0f; // Set second half to 0
a_Buffer[cindex] |= (a_Light << 4) & 0xf0;
}
- MarkDirty();
}
}
@@ -79,7 +78,7 @@ void cChunk::SetLight(char* a_Buffer, int a_BlockIdx, char a_Light)
__C_CHUNK_INLINE__
-void cChunk::SetLight(char* a_Buffer, int x, int y, int z, char light)
+void cChunk::SetNibble(char* a_Buffer, int x, int y, int z, char light)
{
if( x < c_ChunkWidth && x > -1 && y < c_ChunkHeight && y > -1 && z < c_ChunkWidth && z > -1 )
{
@@ -94,7 +93,6 @@ void cChunk::SetLight(char* a_Buffer, int x, int y, int z, char light)
a_Buffer[cindex] &= 0x0f; // Set second half to 0
a_Buffer[cindex] |= (light << 4) & 0xf0;
}
- MarkDirty();
}
}
@@ -105,13 +103,14 @@ void cChunk::SetLight(char* a_Buffer, int x, int y, int z, char light)
__C_CHUNK_INLINE__
void cChunk::SpreadLightOfBlock(char* a_LightBuffer, int a_X, int a_Y, int a_Z, char a_Falloff)
{
- unsigned char CurrentLight = GetLight( a_LightBuffer, a_X, a_Y, a_Z );
- SetLight( a_LightBuffer, a_X-1, a_Y, a_Z, MAX(GetLight( a_LightBuffer, a_X-1, a_Y, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- SetLight( a_LightBuffer, a_X+1, a_Y, a_Z, MAX(GetLight( a_LightBuffer, a_X+1, a_Y, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- SetLight( a_LightBuffer, a_X, a_Y-1, a_Z, MAX(GetLight( a_LightBuffer, a_X, a_Y-1, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- SetLight( a_LightBuffer, a_X, a_Y+1, a_Z, MAX(GetLight( a_LightBuffer, a_X, a_Y+1, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
- SetLight( a_LightBuffer, a_X, a_Y, a_Z-1, MAX(GetLight( a_LightBuffer, a_X, a_Y, a_Z-1 ), MAX(0,CurrentLight-a_Falloff) ) );
- SetLight( a_LightBuffer, a_X, a_Y, a_Z+1, MAX(GetLight( a_LightBuffer, a_X, a_Y, a_Z+1 ), MAX(0,CurrentLight-a_Falloff) ) );
+ unsigned char CurrentLight = GetNibble( a_LightBuffer, a_X, a_Y, a_Z );
+ SetNibble( a_LightBuffer, a_X-1, a_Y, a_Z, MAX(GetNibble( a_LightBuffer, a_X-1, a_Y, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
+ SetNibble( a_LightBuffer, a_X+1, a_Y, a_Z, MAX(GetNibble( a_LightBuffer, a_X+1, a_Y, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
+ SetNibble( a_LightBuffer, a_X, a_Y-1, a_Z, MAX(GetNibble( a_LightBuffer, a_X, a_Y-1, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
+ SetNibble( a_LightBuffer, a_X, a_Y+1, a_Z, MAX(GetNibble( a_LightBuffer, a_X, a_Y+1, a_Z ), MAX(0,CurrentLight-a_Falloff) ) );
+ SetNibble( a_LightBuffer, a_X, a_Y, a_Z-1, MAX(GetNibble( a_LightBuffer, a_X, a_Y, a_Z-1 ), MAX(0,CurrentLight-a_Falloff) ) );
+ SetNibble( a_LightBuffer, a_X, a_Y, a_Z+1, MAX(GetNibble( a_LightBuffer, a_X, a_Y, a_Z+1 ), MAX(0,CurrentLight-a_Falloff) ) );
+ MarkDirty();
}
@@ -121,9 +120,10 @@ void cChunk::SpreadLightOfBlock(char* a_LightBuffer, int a_X, int a_Y, int a_Z,
__C_CHUNK_INLINE__
void cChunk::SpreadLightOfBlockX(char* a_LightBuffer, int a_X, int a_Y, int a_Z)
{
- unsigned char CurrentLight = GetLight( a_LightBuffer, a_X, a_Y, a_Z );
- SetLight( a_LightBuffer, a_X-1, a_Y, a_Z, MAX(GetLight( a_LightBuffer, a_X-1, a_Y, a_Z ), CurrentLight-1) );
- SetLight( a_LightBuffer, a_X+1, a_Y, a_Z, MAX(GetLight( a_LightBuffer, a_X+1, a_Y, a_Z ), CurrentLight-1) );
+ unsigned char CurrentLight = GetNibble( a_LightBuffer, a_X, a_Y, a_Z );
+ SetNibble( a_LightBuffer, a_X-1, a_Y, a_Z, MAX(GetNibble( a_LightBuffer, a_X-1, a_Y, a_Z ), CurrentLight-1) );
+ SetNibble( a_LightBuffer, a_X+1, a_Y, a_Z, MAX(GetNibble( a_LightBuffer, a_X+1, a_Y, a_Z ), CurrentLight-1) );
+ MarkDirty();
}
@@ -133,9 +133,10 @@ void cChunk::SpreadLightOfBlockX(char* a_LightBuffer, int a_X, int a_Y, int a_Z)
__C_CHUNK_INLINE__
void cChunk::SpreadLightOfBlockY(char* a_LightBuffer, int a_X, int a_Y, int a_Z)
{
- unsigned char CurrentLight = GetLight( a_LightBuffer, a_X, a_Y, a_Z );
- SetLight( a_LightBuffer, a_X, a_Y-1, a_Z, MAX(GetLight( a_LightBuffer, a_X, a_Y-1, a_Z ), CurrentLight-1) );
- SetLight( a_LightBuffer, a_X, a_Y+1, a_Z, MAX(GetLight( a_LightBuffer, a_X, a_Y+1, a_Z ), CurrentLight-1) );
+ unsigned char CurrentLight = GetNibble( a_LightBuffer, a_X, a_Y, a_Z );
+ SetNibble( a_LightBuffer, a_X, a_Y-1, a_Z, MAX(GetNibble( a_LightBuffer, a_X, a_Y-1, a_Z ), CurrentLight-1) );
+ SetNibble( a_LightBuffer, a_X, a_Y+1, a_Z, MAX(GetNibble( a_LightBuffer, a_X, a_Y+1, a_Z ), CurrentLight-1) );
+ MarkDirty();
}
@@ -145,9 +146,10 @@ void cChunk::SpreadLightOfBlockY(char* a_LightBuffer, int a_X, int a_Y, int a_Z)
__C_CHUNK_INLINE__
void cChunk::SpreadLightOfBlockZ(char* a_LightBuffer, int a_X, int a_Y, int a_Z)
{
- unsigned char CurrentLight = GetLight( a_LightBuffer, a_X, a_Y, a_Z );
- SetLight( a_LightBuffer, a_X, a_Y, a_Z-1, MAX(GetLight( a_LightBuffer, a_X, a_Y, a_Z-1 ), CurrentLight-1) );
- SetLight( a_LightBuffer, a_X, a_Y, a_Z+1, MAX(GetLight( a_LightBuffer, a_X, a_Y, a_Z+1 ), CurrentLight-1) );
+ unsigned char CurrentLight = GetNibble( a_LightBuffer, a_X, a_Y, a_Z );
+ SetNibble( a_LightBuffer, a_X, a_Y, a_Z-1, MAX(GetNibble( a_LightBuffer, a_X, a_Y, a_Z-1 ), CurrentLight-1) );
+ SetNibble( a_LightBuffer, a_X, a_Y, a_Z+1, MAX(GetNibble( a_LightBuffer, a_X, a_Y, a_Z+1 ), CurrentLight-1) );
+ MarkDirty();
}
diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp
index 0f0cc03a4..beccaefb1 100644
--- a/source/cChunkMap.cpp
+++ b/source/cChunkMap.cpp
@@ -343,6 +343,22 @@ bool cChunkMap::GetChunkBlocks(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char *
+bool cChunkMap::GetChunkBlockData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ return false;
+ }
+ Chunk->GetBlockData(a_BlockData);
+ return true;
+}
+
+
+
+
+
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
@@ -469,14 +485,17 @@ void cChunkMap::CollectPickupsByPlayer(cPlayer * a_Player)
int OtherChunkX = ChunkX + ((BlockX > 8) ? 1 : -1);
int OtherChunkZ = ChunkZ + ((BlockZ > 8) ? 1 : -1);
+ // We suppose that each player keeps their chunks in memory, therefore it makes little sense to try to re-load or even generate them.
+ // The only time the chunks are not valid is when the player is downloading the initial world and they should not call this at that moment
+
cCSLock Lock(m_CSLayers);
- GetChunkNoGen(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer(a_Player);
// Check the neighboring chunks as well:
- GetChunkNoGen(OtherChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
- GetChunkNoGen(OtherChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
- GetChunkNoGen(ChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
- GetChunkNoGen(ChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(OtherChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(OtherChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(ChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(ChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
}
@@ -511,7 +530,7 @@ char cChunkMap::GetBlockMeta(int a_X, int a_Y, int a_Z)
if ((Chunk != NULL) && Chunk->IsValid() )
{
// Although it is called GetLight(), it actually gets meta when passed the Meta field
- return Chunk->GetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z );
+ return cChunk::GetNibble( Chunk->pGetMeta(), a_X, a_Y, a_Z );
}
return 0;
}
@@ -529,8 +548,8 @@ void cChunkMap::SetBlockMeta(int a_X, int a_Y, int a_Z, char a_BlockMeta)
cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
if ((Chunk != NULL) && Chunk->IsValid() )
{
- // Although it is called SetLight(), it actually sets meta when passed the Meta field
- Chunk->SetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z, a_BlockMeta );
+ cChunk::SetNibble( Chunk->pGetMeta(), a_X, a_Y, a_Z, a_BlockMeta );
+ Chunk->MarkDirty();
Chunk->SendBlockTo( a_X, a_Y, a_Z, NULL );
}
}
@@ -706,22 +725,6 @@ void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoo
-bool cChunkMap::SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
-{
- cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
- if ((Chunk == NULL) || !Chunk->IsValid())
- {
- return false;
- }
- Chunk->SendTo(a_Client);
- return true;
-}
-
-
-
-
-
void cChunkMap::MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
diff --git a/source/cChunkMap.h b/source/cChunkMap.h
index 32ae4da6e..f5a750f87 100644
--- a/source/cChunkMap.h
+++ b/source/cChunkMap.h
@@ -45,7 +45,13 @@ public:
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void ChunkDataGenerated (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
+
+ /// Gets the chunk's blocks, only the block types
bool GetChunkBlocks (int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_Blocks);
+
+ /// Gets the chunk's blockdata, the entire array
+ bool GetChunkBlockData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData);
+
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
void SpreadChunkLighting(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
@@ -71,9 +77,6 @@ public:
/// Removes the client from all chunks specified
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
- /// Sends a chunk to client, returns true if successful, false if not sent
- bool SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
-
/// Moves the entity from its current chunk to the new chunk specified
void MoveEntityToChunk(cEntity * a_Entity, int a_ChunkX, int a_ChunkY, int a_ChunkZ);
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index f27ca9e61..9ea063f11 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -1681,35 +1681,6 @@ void cClientHandle::Tick(float a_Dt)
Send(Ping);
m_LastPingTime = m_PingStartTime;
}
-
- if (m_State >= csDownloadingWorld)
- {
- cWorld * World = m_Player->GetWorld();
-
- cCSLock Lock(m_CSChunkLists);
-
- // Send the chunks:
- int NumSent = 0;
- for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end();)
- {
- if (!World->SendChunkTo(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ, this))
- {
- ++itr;
- continue;
- }
- itr = m_ChunksToSend.erase(itr);
- NumSent++;
- if (NumSent > 10)
- {
- // Only send up to 10 chunks per tick, otherwise we'd choke the tick thread
- break;
- }
- } // for itr - m_ChunksToSend[]
- Lock.Unlock();
-
- // Check even if we didn't send anything - a chunk may have sent a notification that we'd miss otherwise
- CheckIfWorldDownloaded();
- }
}
@@ -1737,20 +1708,38 @@ void cClientHandle::Send(const cPacket * a_Packet, ENUM_PRIORITY a_Priority /* =
case E_PLAYERMOVELOOK:
case E_KEEP_ALIVE:
case E_PRE_CHUNK:
+ case E_MAP_CHUNK:
{
// Allow
break;
}
- case E_MAP_CHUNK:
+ default: return;
+ }
+ }
+
+ // Check chunks being sent, erase them from m_ChunksToSend:
+ if (a_Packet->m_PacketID == E_MAP_CHUNK)
+ {
+ #if (MINECRAFT_1_2_2 == 1)
+ int ChunkX = ((cPacket_MapChunk *)a_Packet)->m_PosX;
+ int ChunkZ = ((cPacket_MapChunk *)a_Packet)->m_PosZ;
+ #else
+ int ChunkX = ((cPacket_MapChunk *)a_Packet)->m_PosX / cChunk::c_ChunkWidth;
+ int ChunkZ = ((cPacket_MapChunk *)a_Packet)->m_PosZ / cChunk::c_ChunkWidth;
+ #endif
+ cCSLock Lock(m_CSChunkLists);
+ for (cChunkCoordsList::iterator itr = m_ChunksToSend.begin(); itr != m_ChunksToSend.end(); ++itr)
+ {
+ if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
{
+ m_ChunksToSend.erase(itr);
CheckIfWorldDownloaded();
break;
}
-
- default: return;
- }
+ } // for itr - m_ChunksToSend[]
}
+ // Optimize away multiple queued RelativeEntityMoveLook packets:
cCSLock Lock(m_CSPackets);
if (a_Priority == E_PRIORITY_NORMAL)
{
diff --git a/source/cClientHandle.h b/source/cClientHandle.h
index 3fcfef716..6ac6e07b8 100644
--- a/source/cClientHandle.h
+++ b/source/cClientHandle.h
@@ -94,6 +94,8 @@ public:
bool IsDestroyed() { return m_bDestroyed; }
void Destroy();
+
+ bool IsPlaying(void) const {return (m_State == csPlaying); }
void Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority = E_PRIORITY_NORMAL) { Send(&a_Packet, a_Priority); }
void Send(const cPacket * a_Packet, ENUM_PRIORITY a_Priority = E_PRIORITY_NORMAL);
diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp
index f013465de..673d0b41a 100644
--- a/source/cPlayer.cpp
+++ b/source/cPlayer.cpp
@@ -177,6 +177,12 @@ cPacket * cPlayer::GetSpawnPacket(void) const
void cPlayer::Tick(float a_Dt)
{
+ if (!m_ClientHandle->IsPlaying())
+ {
+ // We're not yet in the game, ignore everything
+ return;
+ }
+
cPawn::Tick(a_Dt);
if (m_bDirtyOrientation && !m_bDirtyPosition)
@@ -233,7 +239,7 @@ void cPlayer::Tick(float a_Dt)
m_ClientHandle->StreamChunks();
}
- if ( m_Health > 0 ) // make sure player is alive
+ if (m_Health > 0) // make sure player is alive
{
m_World->CollectPickupsByPlayer(this);
}
diff --git a/source/cSignEntity.cpp b/source/cSignEntity.cpp
index c181deae2..3f0befc3f 100644
--- a/source/cSignEntity.cpp
+++ b/source/cSignEntity.cpp
@@ -81,25 +81,17 @@ AString cSignEntity::GetLine( int a_Index ) const
-void cSignEntity::SendTo( cClientHandle* a_Client )
+cPacket * cSignEntity::GetPacket(void)
{
- cPacket_UpdateSign Sign;
- Sign.m_PosX = m_PosX;
- Sign.m_PosY = (short)m_PosY;
- Sign.m_PosZ = m_PosZ;
- Sign.m_Line1 = m_Line[0];
- Sign.m_Line2 = m_Line[1];
- Sign.m_Line3 = m_Line[2];
- Sign.m_Line4 = m_Line[3];
-
- if ( a_Client != NULL )
- {
- a_Client->Send( Sign );
- }
- else // broadcast of a_Client == 0
- {
- m_World->BroadcastToChunkOfBlock(m_PosX, m_PosY, m_PosZ, &Sign );
- }
+ cPacket_UpdateSign * Sign = new cPacket_UpdateSign;
+ Sign->m_PosX = m_PosX;
+ Sign->m_PosY = (short)m_PosY;
+ Sign->m_PosZ = m_PosZ;
+ Sign->m_Line1 = m_Line[0];
+ Sign->m_Line2 = m_Line[1];
+ Sign->m_Line3 = m_Line[2];
+ Sign->m_Line4 = m_Line[3];
+ return Sign;
}
diff --git a/source/cSignEntity.h b/source/cSignEntity.h
index bc45e5ff4..5d9d11a9c 100644
--- a/source/cSignEntity.h
+++ b/source/cSignEntity.h
@@ -34,7 +34,8 @@ public:
AString GetLine( int a_Index ) const;
virtual void UsedBy( cPlayer * a_Player ) override;
- virtual void SendTo( cClientHandle* a_Client ) override;
+
+ virtual cPacket * GetPacket(void) override;
private:
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index 2b0f4ab2b..daf34d8f1 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -238,6 +238,8 @@ cWorld::cWorld( const AString & a_WorldName )
}
m_ChunkMap = new cChunkMap(this );
+
+ m_ChunkSender.Start(this);
m_Time = 0;
m_WorldTimeFraction = 0.f;
@@ -975,6 +977,7 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cWorld::ChunkDataLoaded(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
{
m_ChunkMap->ChunkDataLoaded(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData, a_Entities, a_BlockEntities);
+ m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkY, a_ChunkZ);
}
@@ -984,6 +987,7 @@ void cWorld::ChunkDataLoaded(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const cha
void cWorld::ChunkDataGenerated(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
{
m_ChunkMap->ChunkDataGenerated(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData, a_Entities, a_BlockEntities);
+ m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkY, a_ChunkZ);
}
@@ -1008,6 +1012,15 @@ bool cWorld::GetChunkBlocks(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_B
+bool cWorld::GetChunkBlockData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData)
+{
+ return m_ChunkMap->GetChunkBlockData(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData);
+}
+
+
+
+
+
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
{
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ);
@@ -1279,15 +1292,6 @@ void cWorld::RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoords
-bool cWorld::SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client)
-{
- return m_ChunkMap->SendChunkTo(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client);
-}
-
-
-
-
-
void cWorld::TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
m_ChunkMap->TouchChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
diff --git a/source/cWorld.h b/source/cWorld.h
index 60b393ab8..e4fac9d90 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -15,6 +15,7 @@
#include "WorldStorage.h"
#include "cChunkGenerator.h"
#include "Vector3i.h"
+#include "ChunkSender.h"
@@ -71,7 +72,13 @@ public:
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void ChunkDataGenerated(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
+
+ /// Gets the chunk's blocks, only the block types
bool GetChunkBlocks (int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_Blocks);
+
+ /// Gets the chunk's blockdata, the entire array
+ bool GetChunkBlockData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData);
+
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
void UnloadUnusedChunks(void);
@@ -123,9 +130,6 @@ public:
/// Removes the client from all chunks specified
void RemoveClientFromChunks(cClientHandle * a_Client, const cChunkCoordsList & a_Chunks);
- /// Sends a chunk to client, returns true if successful, false if not sent
- bool SendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cClientHandle * a_Client);
-
/// Touches the chunk, causing it to be loaded or generated
void TouchChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
@@ -284,6 +288,8 @@ private:
sSetBlockList m_FastSetBlockQueue;
cChunkGenerator m_Generator;
+
+ cChunkSender m_ChunkSender;
AString m_WorldName;
diff --git a/source/packets/cPacket_MapChunk.cpp b/source/packets/cPacket_MapChunk.cpp
index d602007e3..6fdd73f12 100644
--- a/source/packets/cPacket_MapChunk.cpp
+++ b/source/packets/cPacket_MapChunk.cpp
@@ -19,16 +19,15 @@ cPacket_MapChunk::~cPacket_MapChunk()
-cPacket_MapChunk::cPacket_MapChunk(cChunk * a_Chunk)
+cPacket_MapChunk::cPacket_MapChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData)
{
- ASSERT(a_Chunk->IsValid());
m_PacketID = E_MAP_CHUNK;
#if (MINECRAFT_1_2_2 == 1 )
// ...
- m_PosX = a_Chunk->GetPosX(); // Chunk coordinates now, instead of block coordinates
- m_PosZ = a_Chunk->GetPosZ();
+ m_PosX = a_ChunkX; // Chunk coordinates now, instead of block coordinates
+ m_PosZ = a_ChunkZ;
m_bContiguous = false;
m_BitMap1 = 0;
@@ -37,52 +36,59 @@ cPacket_MapChunk::cPacket_MapChunk(cChunk * a_Chunk)
m_UnusedInt = 0;
- unsigned int DataSize = (cChunk::c_ChunkHeight/16) * (4096 + 2048 + 2048 + 2048);
- char* AllData = new char[ DataSize ];
- memset( AllData, 0, DataSize );
+ unsigned int DataSize = (cChunk::c_ChunkHeight / 16) * (4096 + 2048 + 2048 + 2048);
+ std::auto_ptr<char> AllData(new char[ DataSize ]);
+ memset( AllData.get(), 0, DataSize );
unsigned int iterator = 0;
- for( int i = 0; i < (cChunk::c_ChunkHeight/16); ++i ) // Old world is only 8*16 high (should be 16*16)
+ for ( int i = 0; i < (cChunk::c_ChunkHeight / 16); ++i )
{
m_BitMap1 |= (1 << i); // This tells what chunks are sent. Use this to NOT send air only chunks (right now everything is sent)
- for( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z ) for( int x = 0; x < 16; ++x )
+ for ( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z ) for( int x = 0; x < 16; ++x )
{
- AllData[iterator] = a_Chunk->GetBlock( x, y+i*16, z );
+ int idx = cChunk::MakeIndex(x, y + i * 16, z);
+ AllData.get()[iterator] = a_BlockData[idx];
++iterator;
- }
+ } // for y, z, x
}
- //Send block metadata
- for( int i = 0; i < (cChunk::c_ChunkHeight/16); ++i )
+
+ // Send block metadata:
+ char * Meta = a_BlockData + cChunk::c_NumBlocks;
+ for ( int i = 0; i < (cChunk::c_ChunkHeight / 16); ++i )
{
- for( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
+ for ( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
{
- for( int x = 0; x < 8; ++x )
+ for ( int x = 0; x < 8; ++x )
{
- AllData[iterator] = a_Chunk->GetLight( a_Chunk->pGetMeta(), x*2+0, y+i*16, z ) | a_Chunk->GetLight( a_Chunk->pGetMeta(), x*2+1, y+i*16, z ) << 4;
+ AllData.get()[iterator] = cChunk::GetNibble(Meta, x * 2 + 0, y + i * 16, z) | (cChunk::GetNibble(Meta, x * 2 + 1, y + i * 16, z ) << 4);
++iterator;
- }
- }
+ } // for x
+ } // for y, z
}
- //Send block light
- for( int i = 0; i < (cChunk::c_ChunkHeight/16); ++i )
+
+ // Send block light:
+ char * Light = Meta + cChunk::c_NumBlocks / 2;
+ for ( int i = 0; i < (cChunk::c_ChunkHeight / 16); ++i )
{
- for( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
+ for ( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
{
- for( int x = 0; x < 8; ++x )
+ for ( int x = 0; x < 8; ++x )
{
- AllData[iterator] = a_Chunk->GetLight( a_Chunk->pGetLight(), x*2+0, y+i*16, z ) | a_Chunk->GetLight( a_Chunk->pGetLight(), x*2+1, y+i*16, z ) << 4;
+ AllData.get()[iterator] = cChunk::GetNibble(Light, x * 2 + 0, y + i * 16, z ) | (cChunk::GetNibble(Light, x * 2 + 1, y + i * 16, z ) << 4);
++iterator;
}
}
}
- //Send sky light
+
+ // Send sky light:
+ char * SkyLight = Light + cChunk::c_NumBlocks / 2;
for( int i = 0; i < (cChunk::c_ChunkHeight/16); ++i )
{
for( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
{
for( int x = 0; x < 8; ++x )
{
- AllData[iterator] = a_Chunk->GetLight( a_Chunk->pGetSkyLight(), x*2+0, y+i*16, z ) | a_Chunk->GetLight( a_Chunk->pGetSkyLight(), x*2+1, y+i*16, z ) << 4;
+ AllData.get()[iterator] = cChunk::GetNibble(SkyLight, x * 2 + 0, y + i * 16, z ) | (cChunk::GetNibble(SkyLight, x * 2 + 1, y + i * 16, z ) << 4);
++iterator;
}
}
@@ -91,17 +97,15 @@ cPacket_MapChunk::cPacket_MapChunk(cChunk * a_Chunk)
uLongf CompressedSize = compressBound( DataSize );
char * CompressedBlockData = new char[CompressedSize];
- compress2( (Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)AllData, DataSize, Z_DEFAULT_COMPRESSION);
-
- delete [] AllData;
+ compress2( (Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)AllData.get(), DataSize, Z_DEFAULT_COMPRESSION);
m_CompressedData = CompressedBlockData;
m_CompressedSize = CompressedSize;
#else
- m_PosX = a_Chunk->GetPosX() * cChunk::c_ChunkWidth; // It has to be block coordinates
- m_PosY = (short)(a_Chunk->GetPosY() * cChunk::c_ChunkHeight);
- m_PosZ = a_Chunk->GetPosZ() * cChunk::c_ChunkWidth;
+ m_PosX = a_ChunkX * cChunk::c_ChunkWidth; // It has to be block coordinates
+ m_PosY = (short)(a_ChunkY * cChunk::c_ChunkHeight);
+ m_PosZ = a_ChunkZ * cChunk::c_ChunkWidth;
m_SizeX = 15;
m_SizeY = 127;
@@ -110,7 +114,7 @@ cPacket_MapChunk::cPacket_MapChunk(cChunk * a_Chunk)
uLongf CompressedSize = compressBound( cChunk::c_BlockDataSize );
char * CompressedBlockData = new char[CompressedSize];
- compress2( (Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)a_Chunk->pGetBlockData(), cChunk::c_BlockDataSize, Z_DEFAULT_COMPRESSION);
+ compress2( (Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)a_BlockData, cChunk::c_BlockDataSize, Z_DEFAULT_COMPRESSION);
m_CompressedData = CompressedBlockData;
m_CompressedSize = CompressedSize;
diff --git a/source/packets/cPacket_MapChunk.h b/source/packets/cPacket_MapChunk.h
index 72cef7d25..db4192457 100644
--- a/source/packets/cPacket_MapChunk.h
+++ b/source/packets/cPacket_MapChunk.h
@@ -7,12 +7,6 @@
-class cChunk;
-
-
-
-
-
class cPacket_MapChunk :
public cPacket
{
@@ -39,6 +33,7 @@ public:
{ m_PacketID = E_MAP_CHUNK; m_CompressedData = 0; }
cPacket_MapChunk( const cPacket_MapChunk & a_Copy );
+ cPacket_MapChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData);
~cPacket_MapChunk();
virtual cPacket* Clone() const { return new cPacket_MapChunk(*this); }
@@ -66,12 +61,6 @@ public:
char * m_CompressedData;
-
-protected:
- friend class cChunk;
-
- cPacket_MapChunk(cChunk * a_Chunk); // Called only from within cChunk, therefore it CAN receive a direct pointer
-
};