summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/cBlockToPickup.cpp5
-rw-r--r--source/cChunk.cpp52
-rw-r--r--source/cChunk.h1
-rw-r--r--source/cChunkMap.cpp2
-rw-r--r--source/cChunkMap.h2
-rw-r--r--source/cClientHandle.cpp28
-rw-r--r--source/cClientHandle.h3
-rw-r--r--source/cPlayer.cpp2
-rw-r--r--source/cWorld.cpp170
-rw-r--r--source/cWorld.h1
10 files changed, 184 insertions, 82 deletions
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<cBlockEntity*>::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<int> 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<int>::const_iterator cii;
+ std::vector<int>::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 );
+
+ 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();
- GetChunk( ChunkX, ChunkY, ChunkZ )->FastSetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta );
+ // 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