diff --git a/VC2010/JsonCpp.vcxproj b/VC2010/JsonCpp.vcxproj
index 7e92d3e51..b467336f2 100644
--- a/VC2010/JsonCpp.vcxproj
+++ b/VC2010/JsonCpp.vcxproj
@@ -18,13 +18,11 @@
StaticLibrary
true
- MultiByte
StaticLibrary
false
true
- MultiByte
@@ -36,12 +34,18 @@
-
+
+ $(Configuration)\$(ProjectName)\
+
+
+ $(Configuration)\$(ProjectName)\
+
Level3
Disabled
..\jsoncpp-src-0.5.0\include;%(AdditionalIncludeDirectories)
+ true
true
@@ -56,6 +60,7 @@
..\jsoncpp-src-0.5.0\include;%(AdditionalIncludeDirectories)
MultiThreaded
Speed
+ true
true
diff --git a/VC2010/MCServer.vcxproj b/VC2010/MCServer.vcxproj
index e36f5eaa8..a7728ea4f 100644
--- a/VC2010/MCServer.vcxproj
+++ b/VC2010/MCServer.vcxproj
@@ -27,8 +27,7 @@
Application
- NotSet
- false
+ true
Application
@@ -37,7 +36,6 @@
Application
- NotSet
Application
@@ -63,13 +61,13 @@
<_ProjectFileVersion>10.0.30319.1
$(SolutionDir)..\
$(SolutionDir)..\
- $(Configuration)\
+ $(Configuration)\$(ProjectName)\
$(Configuration)\
true
true
$(SolutionDir)..\
$(SolutionDir)..\
- $(Configuration)\
+ $(Configuration)\$(ProjectName)\
$(Configuration)\
false
false
@@ -80,21 +78,18 @@
Disabled
..\tolua++-1.0.93\include;..\lua-5.1.4\src;..\zlib-1.2.5;..\mysql-connector\include;..\source\;..\pdcurs34\;..\jsoncpp-src-0.5.0\include;..\squirrel_3_0_1_stable\include;..\squirrel_3_0_1_stable;%(AdditionalIncludeDirectories)
WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)
- false
+ true
Sync
EnableFastChecks
MultiThreadedDebugDLL
true
- StreamingSIMDExtensions2
- Fast
-
-
Level3
- ProgramDatabase
+ EditAndContinue
+ true
/IGNORE:4078 %(AdditionalOptions)
- winmm.lib;ws2_32.lib;Psapi.lib;ZLib.lib;tolua++-1.0.93.lib;lua-5.1.4.lib;WebServer.lib;JsonCpp.lib;squirrel_3_0_1_stable.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;Psapi.lib;%(AdditionalDependencies)
../$(ProjectName)_debug.exe
VLD;./Debug/;%(AdditionalLibraryDirectories)
%(IgnoreSpecificDefaultLibraries)
@@ -159,10 +154,11 @@
true
+ true
/IGNORE:4078 %(AdditionalOptions)
- winmm.lib;ws2_32.lib;Psapi.lib;ZLib.lib;tolua++-1.0.93.lib;lua-5.1.4.lib;WebServer.lib;JsonCpp.lib;squirrel_3_0_1_stable.lib;LIBCMT.LIB;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;Psapi.lib;LIBCMT.LIB;%(AdditionalDependencies)
../$(ProjectName).exe
./Release/;%(AdditionalLibraryDirectories)
LIBCMT;%(IgnoreSpecificDefaultLibraries)
@@ -170,8 +166,7 @@
Console
false
true
-
-
+ UseLinkTimeCodeGeneration
false
@@ -223,6 +218,7 @@
+
@@ -360,6 +356,7 @@
+
@@ -510,26 +507,25 @@
+
+ {adbf25b9-7192-4e54-b35e-8ec47ca5ef86}
+
{5e511191-6f1f-4d0d-940a-b850780963d2}
- false
+
+
+ {4571ce2d-9e18-452f-90d6-94ae8e2406f4}
{67b50249-6cec-444e-a87a-d476112590ed}
- false
+
+
+ {2b4bd5c6-91c0-4a74-939f-b28737fb0dc6}
{f6f43a78-816d-4c37-a07b-68bed529273a}
- false
-
-
-
-
-
-
-
diff --git a/VC2010/MCServer.vcxproj.filters b/VC2010/MCServer.vcxproj.filters
index d817d7679..a6e3af736 100644
--- a/VC2010/MCServer.vcxproj.filters
+++ b/VC2010/MCServer.vcxproj.filters
@@ -400,6 +400,9 @@
{fcc08e08-8dba-47b4-89b0-5dc255bb9b8a}
+
+ {0d6f822b-71eb-406f-b17a-d188c4924283}
+
@@ -802,6 +805,9 @@
Packets\cPacket_ItemData
+
+ cChunkGenerator
+
@@ -1239,6 +1245,9 @@
Packets\cPacket_ItemData
+
+ cChunkGenerator
+
diff --git a/VC2010/WebServer.vcxproj b/VC2010/WebServer.vcxproj
index 934c3803d..03c84d620 100644
--- a/VC2010/WebServer.vcxproj
+++ b/VC2010/WebServer.vcxproj
@@ -26,7 +26,6 @@
StaticLibrary
true
- MultiByte
StaticLibrary
@@ -37,7 +36,6 @@
StaticLibrary
false
true
- MultiByte
StaticLibrary
@@ -61,11 +59,15 @@
-
+
+ $(Configuration)\$(ProjectName)\
+
$(SolutionDir)
-
+
+ $(Configuration)\$(ProjectName)\
+
$(SolutionDir)
@@ -73,6 +75,7 @@
Level3
Disabled
+ true
true
@@ -99,6 +102,7 @@
true
MultiThreaded
Speed
+ true
true
diff --git a/VC2010/ZLib.vcxproj b/VC2010/ZLib.vcxproj
index fcc0538e1..f71a9eed5 100644
--- a/VC2010/ZLib.vcxproj
+++ b/VC2010/ZLib.vcxproj
@@ -25,7 +25,6 @@
StaticLibrary
- MultiByte
true
@@ -35,7 +34,6 @@
StaticLibrary
- MultiByte
StaticLibrary
@@ -63,6 +61,8 @@
$(Configuration)\
$(SolutionDir)
$(Configuration)\
+ $(Configuration)\$(ProjectName)\
+ $(Configuration)\$(ProjectName)\
@@ -70,7 +70,9 @@
true
EnableFastChecks
MultiThreadedDebugDLL
- Level3
+ TurnOffAllWarnings
+ EditAndContinue
+ true
@@ -92,8 +94,9 @@
true
MultiThreaded
true
- Level3
+ TurnOffAllWarnings
Speed
+ true
true
@@ -114,7 +117,6 @@
-
@@ -123,7 +125,6 @@
-
diff --git a/VC2010/ZLib.vcxproj.filters b/VC2010/ZLib.vcxproj.filters
index 7e5dc46b8..b79ce5cce 100644
--- a/VC2010/ZLib.vcxproj.filters
+++ b/VC2010/ZLib.vcxproj.filters
@@ -27,9 +27,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -54,9 +51,6 @@
Source Files
-
- Source Files
-
Source Files
diff --git a/VC2010/clean.bat b/VC2010/clean.bat
index c481e1d03..dfc7a6777 100644
--- a/VC2010/clean.bat
+++ b/VC2010/clean.bat
@@ -16,11 +16,10 @@ del release\*.* /Q
del x64\*.* /Q
del "My Inspector Results"\*.* /Q
del ipch\*.* /Q
-rd release /Q
-rd debug /Q
-rd ipch /Q
+rd release /S /Q
+rd debug /S /Q
+rd ipch /S /Q
rd x64 /Q
rd "My Inspector Results" /Q
-rd ipch /Q
pause
\ No newline at end of file
diff --git a/VC2010/lua-5.1.4.vcxproj b/VC2010/lua-5.1.4.vcxproj
index 503345c0e..d0aa832bf 100644
--- a/VC2010/lua-5.1.4.vcxproj
+++ b/VC2010/lua-5.1.4.vcxproj
@@ -25,7 +25,6 @@
StaticLibrary
- MultiByte
true
@@ -35,7 +34,6 @@
StaticLibrary
- MultiByte
StaticLibrary
@@ -63,15 +61,18 @@
$(Configuration)\
$(SolutionDir)
$(Configuration)\
+ $(Configuration)\$(ProjectName)\
+ $(Configuration)\$(ProjectName)\
Disabled
- true
EnableFastChecks
- Level3
+ TurnOffAllWarnings
EditAndContinue
MultiThreadedDebugDLL
+ true
+ true
@@ -93,9 +94,10 @@
true
MultiThreaded
true
- Level3
+ TurnOffAllWarnings
ProgramDatabase
Speed
+ true
true
diff --git a/VC2010/squirrel_3_0_1_stable.vcxproj b/VC2010/squirrel_3_0_1_stable.vcxproj
index a9c919c03..92b9cc05b 100644
--- a/VC2010/squirrel_3_0_1_stable.vcxproj
+++ b/VC2010/squirrel_3_0_1_stable.vcxproj
@@ -18,13 +18,11 @@
StaticLibrary
true
- MultiByte
StaticLibrary
false
true
- MultiByte
@@ -36,12 +34,18 @@
-
+
+ $(Configuration)\$(ProjectName)\
+
+
+ $(Configuration)\$(ProjectName)\
+
- Level3
+ TurnOffAllWarnings
Disabled
../squirrel_3_0_1_stable/include
+ true
true
@@ -49,13 +53,14 @@
- Level3
+ TurnOffAllWarnings
MaxSpeed
true
true
../squirrel_3_0_1_stable/include
Speed
MultiThreaded
+ true
true
diff --git a/VC2010/tolua++-1.0.93.vcxproj b/VC2010/tolua++-1.0.93.vcxproj
index 9fbec5d5d..3cac62db7 100644
--- a/VC2010/tolua++-1.0.93.vcxproj
+++ b/VC2010/tolua++-1.0.93.vcxproj
@@ -25,7 +25,6 @@
StaticLibrary
- MultiByte
true
@@ -35,7 +34,6 @@
StaticLibrary
- MultiByte
StaticLibrary
@@ -63,6 +61,8 @@
$(Configuration)\
$(SolutionDir)
$(Configuration)\
+ $(Configuration)\$(ProjectName)\
+ $(Configuration)\$(ProjectName)\
@@ -71,8 +71,9 @@
true
EnableFastChecks
MultiThreadedDebugDLL
- Level3
+ TurnOffAllWarnings
EditAndContinue
+ true
@@ -96,9 +97,10 @@
..\lua-5.1.4\src;..\tolua++-1.0.93\include;%(AdditionalIncludeDirectories)
MultiThreaded
true
- Level3
+ TurnOffAllWarnings
ProgramDatabase
Speed
+ true
true
diff --git a/source/cBlockToPickup.cpp b/source/cBlockToPickup.cpp
index c653f5409..6e59e6573 100644
--- a/source/cBlockToPickup.cpp
+++ b/source/cBlockToPickup.cpp
@@ -24,9 +24,8 @@ ENUM_ITEM_ID cBlockToPickup::ToPickup( unsigned char a_BlockID, ENUM_ITEM_ID a_U
if( a_UsedItemID == E_ITEM_SHEARS )
return E_ITEM_LEAVES;
else
- if(rand() % 5 == 0)
- return E_ITEM_SAPLING;
- return E_ITEM_EMPTY;
+ if(rand() % 5 == 0) return E_ITEM_SAPLING;
+ return E_ITEM_EMPTY;
case E_BLOCK_COAL_ORE:
return E_ITEM_COAL;
case E_BLOCK_LAPIS_ORE:
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index 0fe192c0b..86107e1ef 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -69,6 +69,11 @@ struct cChunk::sChunkState
cChunk::~cChunk()
{
//LOG("~cChunk() %i %i %i", m_PosX, m_PosY, m_PosZ );
+ if( !m_pState->m_LoadedByClient.empty() )
+ {
+ LOGWARN("WARNING: Deleting cChunk while it contains %i clients!", m_pState->m_LoadedByClient.size() );
+ }
+
for( std::list::iterator itr = m_pState->m_BlockEntities.begin(); itr != m_pState->m_BlockEntities.end(); ++itr)
{
delete *itr;
@@ -128,23 +133,17 @@ void cChunk::Initialize()
// Clear memory
memset( m_BlockData, 0x00, c_BlockDataSize );
-// LARGE_INTEGER TicksPerSecond;
-// QueryPerformanceFrequency( &TicksPerSecond );
-
GenerateTerrain();
-
-// LARGE_INTEGER start;
-// QueryPerformanceCounter( &start );
+ GenerateFoliage();
CalculateHeightmap();
CalculateLighting();
-// LARGE_INTEGER end;
-// QueryPerformanceCounter( &end );
-// double Time = double( end.QuadPart - start.QuadPart ) / double( TicksPerSecond.QuadPart / 1000 );
-// LOG("Calculated light in %f ms", Time );
-
CreateBlockEntities();
+
+ // During generation, some blocks might have been set by using (Fast)SetBlock() causing this list to fill.
+ // This chunk has not been sent to anybody yet, so there is no need for separately sending block changes when you can send an entire chunk
+ m_pState->m_PendingSendBlocks.clear();
}
else
{
@@ -218,7 +217,7 @@ void cChunk::Tick(float a_Dt)
}
std::map< unsigned int, int > ToTickBlocks = m_pState->m_ToTickBlocks;
- unsigned int NumTickBlocks = ToTickBlocks.size();
+ //unsigned int NumTickBlocks = ToTickBlocks.size();
//if( NumTickBlocks > 0 ) LOG("To tick: %i", NumTickBlocks );
m_pState->m_ToTickBlocks.clear();
bool isRedstone = false;
@@ -740,7 +739,7 @@ float GetNoise( float x, float y, cNoise & a_Noise )
return (oct1 + oct2 + oct3) * flatness + height;
}
-#define PI_2 (1.57079633)
+#define PI_2 (1.57079633f)
float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise )
{
float oct1 = (a_Noise.CubicNoise3D( x*0.1f, y*0.1f, z*0.1f ))*4;
@@ -769,7 +768,7 @@ void cChunk::GenerateTerrain()
{
- const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS;
+ //const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS;
const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT;
const ENUM_BLOCK_ID StoneID = E_BLOCK_STONE;
const ENUM_BLOCK_ID SandID = E_BLOCK_SAND;
@@ -859,6 +858,17 @@ void cChunk::GenerateTerrain()
}
}
}
+}
+
+void cChunk::GenerateFoliage()
+{
+ const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS;
+ const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT;
+ const ENUM_BLOCK_ID SandID = E_BLOCK_SAND;
+ const ENUM_BLOCK_ID SandStoneID = E_BLOCK_SANDSTONE;
+ const ENUM_BLOCK_ID CaveID = E_BLOCK_AIR;
+
+ cNoise m_Noise( m_World->GetWorldSeed() );
for(int z = 0; z < 16; z++) for(int x = 0; x < 16; x++)
{
@@ -882,7 +892,7 @@ void cChunk::GenerateTerrain()
int index3 = MakeIndex( x, TopY-3, z );
int index4 = MakeIndex( x, TopY-4, z );
int index5 = MakeIndex( x, TopY-5, z );
-
+
if( m_BlockType[index] == SandID ) {
if( m_BlockType[index1] == CaveID ) {
@@ -898,19 +908,19 @@ void cChunk::GenerateTerrain()
}
}
-
+
if( m_BlockType[index] == DirtID )
{
m_BlockType[ index ] = (char)GrassID;
}
-
+
// Plant sum trees
{
int xx = x + m_PosX*16;
-// int yy = TopY;
+ // int yy = TopY;
int zz = z + m_PosZ*16;
-
+
float val1 = m_Noise.CubicNoise2D( xx*0.1f, zz*0.1f );
float val2 = m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f );
if( m_BlockType[index] == SandID )
@@ -941,7 +951,7 @@ void cChunk::GenerateTerrain()
m_BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM;
}
}
-
+
}
}
}
@@ -1038,7 +1048,7 @@ void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_B
m_pState->m_PendingSendBlocks.push_back( index );
SetLight( m_BlockMeta, index, a_BlockMeta );
- // ONLY recalculate lighting if it's nessesary!
+ // ONLY recalculate lighting if it's necessary!
if( g_BlockLightValue[ OldBlock ] != g_BlockLightValue[ a_BlockType ]
|| g_BlockSpreadLightFalloff[ OldBlock ] != g_BlockSpreadLightFalloff[ a_BlockType ]
|| g_BlockTransparent[ OldBlock ] != g_BlockTransparent[ a_BlockType ] )
diff --git a/source/cChunk.h b/source/cChunk.h
index 9e117bb94..0145908f5 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -101,6 +101,7 @@ private:
void SaveToJson( Json::Value & a_Value );
void GenerateTerrain();
+ void GenerateFoliage();
void CalculateLighting(); // Recalculate right now
void CalculateHeightmap();
void SpreadLightOfBlock(char* a_LightBuffer, int a_X, int a_Y, int a_Z, char a_Falloff);
diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp
index 855318159..2f8339176 100644
--- a/source/cChunkMap.cpp
+++ b/source/cChunkMap.cpp
@@ -208,6 +208,8 @@ void cChunkMap::AddChunk( cChunk* a_Chunk )
const int LocalZ = a_Chunk->GetPosZ() - LayerZ * LAYER_SIZE;
if( FoundLayer->m_Chunks[ LocalX + LocalZ * LAYER_SIZE ].m_LiveChunk )
LOGWARN("WARNING: Added chunk to layer while it was already loaded!");
+ if( FoundLayer->m_Chunks[ LocalX + LocalZ * LAYER_SIZE ].m_Compressed )
+ LOGWARN("WARNING: Added chunk to layer while a compressed version exists!");
FoundLayer->m_Chunks[ LocalX + LocalZ * LAYER_SIZE ].m_LiveChunk = a_Chunk;
FoundLayer->m_NumChunksLoaded++;
}
diff --git a/source/cChunkMap.h b/source/cChunkMap.h
index d1a289a7d..c728514e1 100644
--- a/source/cChunkMap.h
+++ b/source/cChunkMap.h
@@ -20,6 +20,8 @@ public:
void UnloadUnusedChunks();
bool RemoveEntityFromChunk( cEntity & a_Entity, cChunk* a_CalledFrom = 0 );
void SaveAllChunks();
+
+ cWorld* GetWorld() { return m_World; }
private:
class cChunkData
{
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp
index 548dafeb6..6725a2156 100644
--- a/source/cClientHandle.cpp
+++ b/source/cClientHandle.cpp
@@ -249,12 +249,19 @@ void cClientHandle::StreamChunks()
int ChunkPosX = (int)floor(m_Player->GetPosX() / 16);
int ChunkPosZ = (int)floor(m_Player->GetPosZ() / 16);
- cChunk* NeededChunks[VIEWDISTANCE*VIEWDISTANCE];
- for(int x = 0; x < VIEWDISTANCE; x++)
+ cWorld* World = m_Player->GetWorld();
+
+ cChunk* NeededChunks[VIEWDISTANCE*VIEWDISTANCE] = { 0 };
+ const int MaxDist = VIEWDISTANCE+GENERATEDISTANCE*2;
+ for(int x = 0; x < MaxDist; x++)
{
- for(int z = 0; z < VIEWDISTANCE; z++)
+ for(int z = 0; z < MaxDist; z++)
{
- NeededChunks[x + z*VIEWDISTANCE] = m_Player->GetWorld()->GetChunk( x + ChunkPosX-(VIEWDISTANCE-1)/2, 0, z + ChunkPosZ-(VIEWDISTANCE-1)/2 );
+ int RelX = x - (MaxDist-1)/2;
+ int RelZ = z - (MaxDist-1)/2;
+ cChunk* Chunk = World->GetChunk( ChunkPosX + RelX, 0, ChunkPosZ + RelZ ); // Touch all chunks in wide range, so they get generated
+ if( x >= GENERATEDISTANCE && x < VIEWDISTANCE+GENERATEDISTANCE && z >= GENERATEDISTANCE && z < VIEWDISTANCE+GENERATEDISTANCE ) // but player only needs chunks in view distance
+ NeededChunks[(x-GENERATEDISTANCE) + (z-GENERATEDISTANCE)*VIEWDISTANCE] = Chunk;
}
}
@@ -263,6 +270,9 @@ void cClientHandle::StreamChunks()
unsigned int MissIndex = 0;
for(int i = 0; i < VIEWDISTANCE*VIEWDISTANCE; i++) // Handshake loop - touch each chunk once
{
+ if( NeededChunks[i] == 0 ) continue; // Chunk is not yet loaded, so ignore
+ // This can cause MissIndex to be 0 and thus chunks will not be unloaded while they are actually out of range,
+ // which might actually be a good thing, otherwise it would keep trying to unload chunks until the new chunks are fully loaded
bool bChunkMissing = true;
for(int j = 0; j < VIEWDISTANCE*VIEWDISTANCE; j++)
{
@@ -280,7 +290,7 @@ void cClientHandle::StreamChunks()
}
if( MissIndex > 0 )
- { // Chunks are gonna be streamed in, so chunks probably also need to be streamed out
+ { // Chunks are gonna be streamed in, so chunks probably also need to be streamed out <- optimization
for(int x = 0; x < VIEWDISTANCE; x++)
{
for(int z = 0; z < VIEWDISTANCE; z++)
@@ -294,7 +304,10 @@ void cClientHandle::StreamChunks()
|| Chunk->GetPosZ() > ChunkPosZ+(VIEWDISTANCE-1)/2 )
{
Chunk->RemoveClient( this );
- Chunk->AsyncUnload( this );
+ Chunk->AsyncUnload( this ); // TODO - I think it's possible to unload the chunk immediately instead of next tick
+ // I forgot why I made it happen next tick
+
+ m_LoadedChunks[x + z*VIEWDISTANCE] = 0;
}
}
}
@@ -306,6 +319,7 @@ void cClientHandle::StreamChunks()
}
}
+// Sends chunks to the player from the player position outward
void cClientHandle::StreamChunksSmart( cChunk** a_Chunks, unsigned int a_NumChunks )
{
int X = (int)floor(m_Player->GetPosX() / 16);
@@ -392,7 +406,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet )
LOGINFO("Got Create Inventory Action packet");
}
break;
- case E_PING: // Somebody tries to retreive information about the server
+ case E_PING: // Somebody tries to retrieve information about the server
{
LOGINFO("Got ping");
char NumPlayers[8], cMaxPlayers[8];
diff --git a/source/cClientHandle.h b/source/cClientHandle.h
index 5025f03d2..048e46389 100644
--- a/source/cClientHandle.h
+++ b/source/cClientHandle.h
@@ -20,7 +20,8 @@ public:
cClientHandle(const cSocket & a_Socket);
~cClientHandle();
- static const int VIEWDISTANCE = 13;
+ static const int VIEWDISTANCE = 13; // MUST be odd number or CRASH!
+ static const int GENERATEDISTANCE = 2; // Server generates this many chunks AHEAD of player sight.
const cSocket & GetSocket();
cPlayer* GetPlayer() { return m_Player; } // tolua_export
diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp
index 2087f7927..5a005005d 100644
--- a/source/cPlayer.cpp
+++ b/source/cPlayer.cpp
@@ -147,6 +147,8 @@ void cPlayer::SpawnOn( cClientHandle* a_Target )
void cPlayer::Tick(float a_Dt)
{
cChunk* InChunk = GetWorld()->GetChunk( m_ChunkX, m_ChunkY, m_ChunkZ );
+ if( !InChunk ) return;
+
if(m_bDirtyOrientation && !m_bDirtyPosition)
{
cPacket_EntityLook EntityLook( this );
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index 2f5ed1c2b..1dc4de6ac 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -33,6 +33,7 @@
#include "cZombiepigman.h" //Zombiepigman
#include "cGenSettings.h"
#include "cMakeDir.h"
+#include "cChunkGenerator.h"
#include "packets/cPacket_TimeUpdate.h"
@@ -67,17 +68,33 @@ inline float fRadRand( float a_Radius )
return ((float)rand() * RECI_RAND_MAX)*a_Radius - a_Radius*0.5f;
}
+struct sSetBlockData
+{
+ sSetBlockData( int a_X, int a_Y, int a_Z, char a_BlockID, char a_BlockMeta )
+ : x( a_X )
+ , y( a_Y )
+ , z( a_Z )
+ , BlockID( a_BlockID )
+ , BlockMeta( a_BlockMeta )
+ {}
+ int x, y, z;
+ char BlockID, BlockMeta;
+};
+
+typedef std::list< sSetBlockData > FastSetBlockList;
+
struct cWorld::sWorldState
{
- cWorld::EntityList m_RemoveEntityQueue;
- cWorld::EntityList m_AllEntities;
- cWorld::ClientList m_Clients;
- cWorld::PlayerList m_Players;
+ cWorld::EntityList RemoveEntityQueue;
+ cWorld::EntityList AllEntities;
+ cWorld::ClientList Clients;
+ cWorld::PlayerList Players;
- static const unsigned int CHUNKBUFFER_SIZE = 5;
- std::vector< unsigned int > m_ChunkBuffer;
+ cWorld::ChunkList SpreadQueue;
- cWorld::ChunkList m_SpreadQueue;
+ FastSetBlockList FastSetBlockQueue;
+
+ cChunkGenerator* pChunkGenerator;
std::string WorldName;
};
@@ -91,10 +108,10 @@ cWorld* cWorld::GetWorld()
cWorld::~cWorld()
{
LockEntities();
- while( m_pState->m_AllEntities.begin() != m_pState->m_AllEntities.end() )
+ while( m_pState->AllEntities.begin() != m_pState->AllEntities.end() )
{
- cEntity* Entity = *m_pState->m_AllEntities.begin();
- m_pState->m_AllEntities.remove( Entity );
+ cEntity* Entity = *m_pState->AllEntities.begin();
+ m_pState->AllEntities.remove( Entity );
if( !Entity->IsDestroyed() ) Entity->Destroy();
RemoveEntity( Entity );
}
@@ -104,6 +121,7 @@ cWorld::~cWorld()
delete m_LavaSimulator;
UnloadUnusedChunks();
+ delete m_pState->pChunkGenerator;
delete m_ChunkMap;
delete m_ClientHandleCriticalSection; m_ClientHandleCriticalSection = 0;
@@ -188,6 +206,7 @@ cWorld::cWorld( const char* a_WorldName )
}
m_ChunkMap = new cChunkMap( 32, 32, this );
+ m_pState->pChunkGenerator = new cChunkGenerator( m_ChunkMap );
m_Time = 0;
m_WorldTimeFraction = 0.f;
@@ -376,13 +395,13 @@ void cWorld::Tick(float a_Dt)
LockChunks();
- while( !m_pState->m_SpreadQueue.empty() )
+ while( !m_pState->SpreadQueue.empty() )
{
- cChunk* Chunk = (*m_pState->m_SpreadQueue.begin());
+ cChunk* Chunk = (*m_pState->SpreadQueue.begin());
//LOG("Spreading: %p", Chunk );
Chunk->SpreadLight( Chunk->pGetSkyLight() );
Chunk->SpreadLight( Chunk->pGetLight() );
- m_pState->m_SpreadQueue.remove( &*Chunk );
+ m_pState->SpreadQueue.remove( &*Chunk );
}
m_ChunkMap->Tick(a_Dt);
@@ -427,6 +446,16 @@ void cWorld::Tick(float a_Dt)
}
////////////////Weather///////////////////////
+ // Asynchronously set blocks
+ FastSetBlockList FastSetBlockQueueCopy = m_pState->FastSetBlockQueue;
+ m_pState->FastSetBlockQueue.clear();
+ for( FastSetBlockList::iterator itr = FastSetBlockQueueCopy.begin(); itr != FastSetBlockQueueCopy.end(); ++itr )
+ {
+ sSetBlockData & SetBlockData = *itr;
+ FastSetBlock( SetBlockData.x, SetBlockData.y, SetBlockData.z, SetBlockData.BlockID, SetBlockData.BlockMeta ); // If unable to set block, it's added to FastSetBlockQueue again
+ }
+ if( FastSetBlockQueueCopy.size() != m_pState->FastSetBlockQueue.size() )
+ LOG(" Before: %i, after %i" , FastSetBlockQueueCopy.size(), m_pState->FastSetBlockQueue.size() );
if( m_Time - m_LastSave > 60*5 ) // Save each 5 minutes
{
@@ -438,15 +467,15 @@ void cWorld::Tick(float a_Dt)
UnloadUnusedChunks();
}
- while( !m_pState->m_RemoveEntityQueue.empty() )
+ while( !m_pState->RemoveEntityQueue.empty() )
{
- RemoveEntity( *m_pState->m_RemoveEntityQueue.begin() );
+ RemoveEntity( *m_pState->RemoveEntityQueue.begin() );
}
if( m_bAnimals && ( m_Time - m_SpawnMonsterTime > m_SpawnMonsterRate ) ) // 10 seconds
{
m_SpawnMonsterTime = m_Time;
- if( m_pState->m_Players.size() > 0 )
+ if( m_pState->Players.size() > 0 )
{
cMonster *Monster = 0;
@@ -454,8 +483,8 @@ void cWorld::Tick(float a_Dt)
int dayRand = rand() % 6; //added mob code
int nightRand = rand() % 10; //added mob code
- int RandomPlayerIdx = rand() & m_pState->m_Players.size();
- PlayerList::iterator itr = m_pState->m_Players.begin();
+ int RandomPlayerIdx = rand() & m_pState->Players.size();
+ PlayerList::iterator itr = m_pState->Players.begin();
for( int i = 1; i < RandomPlayerIdx; i++ )
itr++;
@@ -516,12 +545,12 @@ void cWorld::Tick(float a_Dt)
std::vector m_RSList_copy(m_RSList);
//copy(m_RSList.begin(), m_RSList.end(), m_RSList_copy.begin());
m_RSList.erase(m_RSList.begin(),m_RSList.end());
- int tempX;
+ int tempX; // FIXME - Keep the scope in mind, these variables are not used in this scope at all, move them down into the for loop
int tempY;
int tempZ;
int state;
- std::vector::const_iterator cii;
+ std::vector::const_iterator cii; // FIXME - Please rename this variable, WTF is cii??? Use human readable variable names or common abbreviations (i, idx, itr, iter)
for(cii=m_RSList_copy.begin(); cii!=m_RSList_copy.end();)
{
tempX = *cii;cii++;
@@ -612,7 +641,7 @@ void cWorld::UnloadUnusedChunks()
UnlockChunks();
}
-cChunk* cWorld::GetChunk( int a_X, int a_Y, int a_Z )
+cChunk* cWorld::GetChunkReliable( int a_X, int a_Y, int a_Z ) // TODO - FIXME - WARNING - This can cause a duplicate chunk to be generated!!
{
cChunk* Chunk = GetChunkUnreliable( a_X, a_Y, a_Z );
if( Chunk )
@@ -632,7 +661,20 @@ cChunk* cWorld::GetChunk( int a_X, int a_Y, int a_Z )
return Chunk;
}
- // This should never happen, but yeah
+ // This should never happen since it's reliable, but yeah
+ return 0;
+}
+
+cChunk* cWorld::GetChunk( int a_X, int a_Y, int a_Z )
+{
+ // Get chunk from memory
+ cChunk* Chunk = GetChunkUnreliable( a_X, a_Y, a_Z );
+ if( Chunk ) return Chunk;
+
+ // Generate new chunk asynchronously
+ m_pState->pChunkGenerator->GenerateChunk( a_X, a_Z );
+
+ // Could not find chunk, it's being generated, so return 0
return 0;
}
@@ -660,16 +702,37 @@ void cWorld::SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_Block
int ChunkX, ChunkY, ChunkZ;
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
- GetChunk( ChunkX, ChunkY, ChunkZ )->SetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta );
+ cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
+ if( Chunk ) Chunk->SetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta );
}
void cWorld::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta )
{
- int ChunkX, ChunkY, ChunkZ;
+ int ChunkX, ChunkY, ChunkZ, X = a_X, Y = a_Y, Z = a_Z;
- AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
+ AbsoluteToRelative( X, Y, Z, ChunkX, ChunkY, ChunkZ );
- GetChunk( ChunkX, ChunkY, ChunkZ )->FastSetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta );
+ cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
+ if( Chunk )
+ {
+ Chunk->FastSetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
+ return;
+ }
+
+ // Could not find chunk, so it has been pushed into the generate chunks queue
+ // Check if currently generating the target chunk
+ m_pState->pChunkGenerator->Lock();
+ Chunk = m_pState->pChunkGenerator->GetCurrentlyGenerating();
+ if( Chunk && Chunk->GetPosX() == ChunkX && Chunk->GetPosZ() == ChunkZ )
+ {
+ Chunk->FastSetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
+ m_pState->pChunkGenerator->Unlock();
+ return;
+ }
+ m_pState->pChunkGenerator->Unlock();
+
+ // Unable to set block right now, try again later
+ m_pState->FastSetBlockQueue.push_back( sSetBlockData( a_X, a_Y, a_Z, a_BlockType, a_BlockMeta ) );
}
char cWorld::GetBlock( int a_X, int a_Y, int a_Z )
@@ -678,7 +741,9 @@ char cWorld::GetBlock( int a_X, int a_Y, int a_Z )
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
- return GetChunk( ChunkX, ChunkY, ChunkZ )->GetBlock(a_X, a_Y, a_Z);
+ cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
+ if( Chunk ) return Chunk->GetBlock(a_X, a_Y, a_Z);
+ return 0;
}
char cWorld::GetBlockMeta( int a_X, int a_Y, int a_Z )
@@ -688,7 +753,8 @@ char cWorld::GetBlockMeta( int a_X, int a_Y, int a_Z )
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
- return Chunk->GetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z );
+ if( Chunk ) return Chunk->GetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z );
+ return 0;
}
void cWorld::SetBlockMeta( int a_X, int a_Y, int a_Z, char a_MetaData )
@@ -698,8 +764,11 @@ void cWorld::SetBlockMeta( int a_X, int a_Y, int a_Z, char a_MetaData )
AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
- Chunk->SetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z, a_MetaData );
- Chunk->SendBlockTo( a_X, a_Y, a_Z, 0 );
+ if( Chunk )
+ {
+ Chunk->SetLight( Chunk->pGetMeta(), a_X, a_Y, a_Z, a_MetaData );
+ Chunk->SendBlockTo( a_X, a_Y, a_Z, 0 );
+ }
}
bool cWorld::DigBlock( int a_X, int a_Y, int a_Z, cItem & a_PickupItem )
@@ -750,7 +819,8 @@ char cWorld::GetHeight( int a_X, int a_Z )
int PosX = a_X, PosY = 0, PosZ = a_Z, ChunkX, ChunkY, ChunkZ;
AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkY, ChunkZ );
cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
- return Chunk->GetHeight( PosX, PosZ );
+ if( Chunk ) return Chunk->GetHeight( PosX, PosZ );
+ return 0;
}
const double & cWorld::GetSpawnY()
@@ -761,7 +831,7 @@ const double & cWorld::GetSpawnY()
void cWorld::Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude /* = 0 */ )
{
- for( PlayerList::iterator itr = m_pState->m_Players.begin(); itr != m_pState->m_Players.end(); ++itr)
+ for( PlayerList::iterator itr = m_pState->Players.begin(); itr != m_pState->Players.end(); ++itr)
{
if( (*itr)->GetClientHandle() == a_Exclude || !(*itr)->GetClientHandle()->IsLoggedIn() ) continue;
(*itr)->GetClientHandle()->Send( a_Packet );
@@ -789,22 +859,22 @@ void cWorld::SetMaxPlayers(int iMax)
void cWorld::AddPlayer( cPlayer* a_Player )
{
- m_pState->m_Players.remove( a_Player );
- m_pState->m_Players.push_back( a_Player );
+ m_pState->Players.remove( a_Player );
+ m_pState->Players.push_back( a_Player );
}
void cWorld::RemovePlayer( cPlayer* a_Player )
{
- m_pState->m_Players.remove( a_Player );
+ m_pState->Players.remove( a_Player );
}
void cWorld::GetAllPlayers( lua_State* L )
{
- lua_createtable(L, m_pState->m_Players.size(), 0);
+ lua_createtable(L, m_pState->Players.size(), 0);
int newTable = lua_gettop(L);
int index = 1;
- PlayerList::const_iterator iter = m_pState->m_Players.begin();
- while(iter != m_pState->m_Players.end()) {
+ PlayerList::const_iterator iter = m_pState->Players.begin();
+ while(iter != m_pState->Players.end()) {
tolua_pushusertype( L, (*iter), "cPlayer" );
lua_rawseti(L, newTable, index);
++iter;
@@ -820,7 +890,7 @@ cPlayer* cWorld::GetPlayer( const char* a_PlayerName )
bool bPerfectMatch = false;
unsigned int NameLength = strlen( a_PlayerName );
- for( PlayerList::iterator itr = m_pState->m_Players.begin(); itr != m_pState->m_Players.end(); itr++ )
+ for( PlayerList::iterator itr = m_pState->Players.begin(); itr != m_pState->Players.end(); itr++ )
{
std::string Name = (*itr)->GetName();
if( NameLength > Name.length() ) continue; // Definitely not a match
@@ -864,7 +934,7 @@ cPlayer* cWorld::GetPlayer( const char* a_PlayerName )
cEntity* cWorld::GetEntity( int a_UniqueID )
{
- for( EntityList::iterator itr = m_pState->m_AllEntities.begin(); itr != m_pState->m_AllEntities.end(); ++itr )
+ for( EntityList::iterator itr = m_pState->AllEntities.begin(); itr != m_pState->AllEntities.end(); ++itr )
{
if( (*itr)->GetUniqueID() == a_UniqueID )
return *itr;
@@ -884,7 +954,7 @@ cEntity* cWorld::GetEntity( int a_UniqueID )
void cWorld::RemoveEntity( cEntity* a_Entity )
{
- m_pState->m_RemoveEntityQueue.remove( a_Entity );
+ m_pState->RemoveEntityQueue.remove( a_Entity );
if( a_Entity )
{
delete a_Entity;
@@ -943,15 +1013,15 @@ void cWorld::UnlockChunks()
void cWorld::ReSpreadLighting( cChunk* a_Chunk )
{
LockChunks();
- m_pState->m_SpreadQueue.remove( a_Chunk );
- m_pState->m_SpreadQueue.push_back( a_Chunk );
+ m_pState->SpreadQueue.remove( a_Chunk );
+ m_pState->SpreadQueue.push_back( a_Chunk );
UnlockChunks();
}
void cWorld::RemoveSpread( cChunk* a_Chunk )
{
LockChunks();
- m_pState->m_SpreadQueue.remove( a_Chunk );
+ m_pState->SpreadQueue.remove( a_Chunk );
UnlockChunks();
}
@@ -969,24 +1039,24 @@ void cWorld::RemoveSpread( cChunk* a_Chunk )
// }
cWorld::EntityList & cWorld::GetEntities()
{
- return m_pState->m_AllEntities;
+ return m_pState->AllEntities;
}
void cWorld::AddEntity( cEntity* a_Entity )
{
- m_pState->m_AllEntities.push_back( a_Entity );
+ m_pState->AllEntities.push_back( a_Entity );
}
cWorld::PlayerList & cWorld::GetAllPlayers()
{
- return m_pState->m_Players;
+ return m_pState->Players;
}
unsigned int cWorld::GetNumPlayers()
{
- return m_pState->m_Players.size();
+ return m_pState->Players.size();
}
void cWorld::AddToRemoveEntityQueue( cEntity & a_Entity )
{
- m_pState->m_AllEntities.remove( &a_Entity);
- m_pState->m_RemoveEntityQueue.push_back( &a_Entity );
+ m_pState->AllEntities.remove( &a_Entity);
+ m_pState->RemoveEntityQueue.push_back( &a_Entity );
}
const char* cWorld::GetName()
{
diff --git a/source/cWorld.h b/source/cWorld.h
index 83a9bcf66..1e3e1b5a2 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -47,6 +47,7 @@ public:
void SetWorldTime(long long a_WorldTime) { m_WorldTime = a_WorldTime; } //tolua_export
cChunk* GetChunk( int a_X, int a_Y, int a_Z );
+ cChunk* GetChunkReliable( int a_X, int a_Y, int a_Z );
cChunk* GetChunkUnreliable( int a_X, int a_Y, int a_Z );
cChunk* GetChunkOfBlock( int a_X, int a_Y, int a_Z );
char GetHeight( int a_X, int a_Z ); //tolua_export