summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-02-18 18:53:22 +0100
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-02-18 18:53:22 +0100
commit499745c1c7a865941b3c102532777c19dfb92ca4 (patch)
treedeccb8ffdafe6dbb85e8e630eaca0a6e5a66c5ed
parentLogging: added thread ID to the log output in debug builds (diff)
downloadcuberite-499745c1c7a865941b3c102532777c19dfb92ca4.tar
cuberite-499745c1c7a865941b3c102532777c19dfb92ca4.tar.gz
cuberite-499745c1c7a865941b3c102532777c19dfb92ca4.tar.bz2
cuberite-499745c1c7a865941b3c102532777c19dfb92ca4.tar.lz
cuberite-499745c1c7a865941b3c102532777c19dfb92ca4.tar.xz
cuberite-499745c1c7a865941b3c102532777c19dfb92ca4.tar.zst
cuberite-499745c1c7a865941b3c102532777c19dfb92ca4.zip
-rw-r--r--source/WorldStorage.cpp52
-rw-r--r--source/WorldStorage.h16
-rw-r--r--source/cAuthenticator.cpp4
-rw-r--r--source/cChunk.cpp16
-rw-r--r--source/cChunk.h2
-rw-r--r--source/cChunkGenerator.cpp36
-rw-r--r--source/cChunkGenerator.h5
-rw-r--r--source/cChunkMap.cpp59
-rw-r--r--source/cChunkMap.h21
-rw-r--r--source/cPluginManager.cpp1
-rw-r--r--source/cWorld.cpp148
-rw-r--r--source/cWorld.h12
-rw-r--r--source/cWorldGenerator.cpp175
-rw-r--r--source/cWorldGenerator.h9
-rw-r--r--source/cWorldGenerator_Test.cpp23
-rw-r--r--source/cWorldGenerator_Test.h5
16 files changed, 408 insertions, 176 deletions
diff --git a/source/WorldStorage.cpp b/source/WorldStorage.cpp
index f6be97753..bc830c272 100644
--- a/source/WorldStorage.cpp
+++ b/source/WorldStorage.cpp
@@ -147,13 +147,14 @@ void cWorldStorage::WaitForFinish(void)
{
// Cancel all loading requests:
- cCSLock Lock(m_CSLoadQueue);
+ cCSLock Lock(m_CSQueues);
m_LoadQueue.clear();
}
// Wait for the thread to finish:
mShouldTerminate = true;
m_Event.Set();
+ m_evtRemoved.Set(); // Wake up anybody waiting in the WaitForQueuesEmpty() method
super::Wait();
}
@@ -161,10 +162,44 @@ void cWorldStorage::WaitForFinish(void)
+void cWorldStorage::WaitForQueuesEmpty(void)
+{
+ cCSLock Lock(m_CSQueues);
+ while (!mShouldTerminate && (!m_LoadQueue.empty() || !m_SaveQueue.empty()))
+ {
+ cCSUnlock Unlock(Lock);
+ m_evtRemoved.Wait();
+ }
+}
+
+
+
+
+
+int cWorldStorage::GetLoadQueueLength(void)
+{
+ cCSLock Lock(m_CSQueues);
+ return (int)m_LoadQueue.size();
+}
+
+
+
+
+
+int cWorldStorage::GetSaveQueueLength(void)
+{
+ cCSLock Lock(m_CSQueues);
+ return (int)m_SaveQueue.size();
+}
+
+
+
+
+
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
// Queues the chunk for loading; if not loaded, the chunk will be generated
- cCSLock Lock(m_CSLoadQueue);
+ cCSLock Lock(m_CSQueues);
m_LoadQueue.remove (cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); // Don't add twice
m_LoadQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
m_Event.Set();
@@ -176,7 +211,7 @@ void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- cCSLock Lock(m_CSSaveQueue);
+ cCSLock Lock(m_CSQueues);
m_SaveQueue.remove (cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ)); // Don't add twice
m_SaveQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
m_Event.Set();
@@ -188,8 +223,9 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cWorldStorage::UnqueueLoad(const cChunkCoords & a_Chunk)
{
- cCSLock Lock(m_CSLoadQueue);
+ cCSLock Lock(m_CSQueues);
m_LoadQueue.remove(a_Chunk);
+ m_evtRemoved.Set();
}
@@ -198,8 +234,9 @@ void cWorldStorage::UnqueueLoad(const cChunkCoords & a_Chunk)
void cWorldStorage::UnqueueSave(const cChunkCoords & a_Chunk)
{
- cCSLock Lock(m_CSSaveQueue);
+ cCSLock Lock(m_CSQueues);
m_SaveQueue.remove(a_Chunk);
+ m_evtRemoved.Set();
}
@@ -258,6 +295,7 @@ void cWorldStorage::Execute(void)
HasMore = LoadOneChunk();
HasMore = HasMore | SaveOneChunk();
+ m_evtRemoved.Set();
} while (HasMore);
}
}
@@ -272,7 +310,7 @@ bool cWorldStorage::LoadOneChunk(void)
bool HasMore;
bool ShouldLoad = false;
{
- cCSLock Lock(m_CSLoadQueue);
+ cCSLock Lock(m_CSQueues);
if (m_LoadQueue.size() > 0)
{
ToLoad = m_LoadQueue.front();
@@ -299,7 +337,7 @@ bool cWorldStorage::SaveOneChunk(void)
bool HasMore;
bool ShouldSave = false;
{
- cCSLock Lock(m_CSSaveQueue);
+ cCSLock Lock(m_CSQueues);
if (m_SaveQueue.size() > 0)
{
Save = m_SaveQueue.front();
diff --git a/source/WorldStorage.h b/source/WorldStorage.h
index 220585c57..1ea39cf66 100644
--- a/source/WorldStorage.h
+++ b/source/WorldStorage.h
@@ -105,19 +105,23 @@ public:
bool Start(cWorld * a_World, const AString & a_StorageSchemaName); // Hide the cIsThread's Start() method, we need to provide args
void WaitForFinish(void);
+ void WaitForQueuesEmpty(void);
+
+ int GetLoadQueueLength(void);
+ int GetSaveQueueLength(void);
protected:
cWorld * m_World;
AString m_StorageSchemaName;
- cCriticalSection m_CSLoadQueue;
- cChunkCoordsList m_LoadQueue;
-
- cCriticalSection m_CSSaveQueue;
- cChunkCoordsList m_SaveQueue;
+ // Both queues are locked by the same CS
+ cCriticalSection m_CSQueues;
+ cChunkCoordsList m_LoadQueue;
+ cChunkCoordsList m_SaveQueue;
- cEvent m_Event; // Set when there's any addition to the queues
+ cEvent m_Event; // Set when there's any addition to the queues
+ cEvent m_evtRemoved; // Set when an item has been removed from the queue, either by the worker thread or the Unqueue methods
/// All the storage schemas (all used for loading)
cWSSchemaList m_Schemas;
diff --git a/source/cAuthenticator.cpp b/source/cAuthenticator.cpp
index c82b8cec0..0c482a9a1 100644
--- a/source/cAuthenticator.cpp
+++ b/source/cAuthenticator.cpp
@@ -113,7 +113,7 @@ void cAuthenticator::Stop(void)
void cAuthenticator::Execute(void)
{
- while (true)
+ for (;;)
{
cCSLock Lock(mCS);
while (!mShouldTerminate && (mQueue.size() == 0))
@@ -142,7 +142,7 @@ void cAuthenticator::Execute(void)
{
cRoot::Get()->AuthenticateUser(UserName);
}
- }
+ } // for (-ever)
}
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index 5bd6ca1e9..b5e56f3c6 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -109,6 +109,8 @@ void cChunk::SetValid(bool a_SendToClients)
{
m_IsValid = true;
+ m_World->GetChunkMap()->ChunkValidated();
+
if (!a_SendToClients)
{
return;
@@ -177,7 +179,7 @@ void cChunk::MarkSaved(void)
void cChunk::MarkLoaded(void)
{
m_IsDirty = false;
- m_IsValid = true;
+ SetValid();
}
@@ -240,8 +242,6 @@ void cChunk::SetAllData(const char * a_BlockData, cEntityList & a_Entities, cBlo
CreateBlockEntities();
CalculateHeightmap();
-
- MarkDirty();
}
@@ -511,7 +511,7 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom)
-char cChunk::GetHeight( int a_X, int a_Z )
+int cChunk::GetHeight( int a_X, int a_Z )
{
if( a_X >= 0 && a_X < 16 && a_Z >= 0 && a_Z < 16 )
{
@@ -756,10 +756,10 @@ void cChunk::SpreadLight(char* a_LightBuffer)
}
}
- if( bCalcLeft ) m_World->ReSpreadLighting( LeftChunk );
- if( bCalcRight ) m_World->ReSpreadLighting( RightChunk );
- if( bCalcFront ) m_World->ReSpreadLighting( FrontChunk );
- if( bCalcBack ) m_World->ReSpreadLighting( BackChunk );
+ 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 );
}
diff --git a/source/cChunk.h b/source/cChunk.h
index b750e10db..60e11b133 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -119,7 +119,7 @@ public:
void CollectPickupsByPlayer(cPlayer * a_Player);
void UpdateSign(int a_PosX, int a_PosY, int a_PosZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); // Also sends update packets to all clients in the chunk
- char GetHeight( int a_X, int a_Z );
+ int GetHeight( int a_X, int a_Z );
void SendBlockTo( int a_X, int a_Y, int a_Z, cClientHandle* a_Client );
diff --git a/source/cChunkGenerator.cpp b/source/cChunkGenerator.cpp
index 5c8144f05..c0fea1fae 100644
--- a/source/cChunkGenerator.cpp
+++ b/source/cChunkGenerator.cpp
@@ -71,6 +71,7 @@ void cChunkGenerator::Stop(void)
{
mShouldTerminate = true;
m_Event.Set();
+ m_evtRemoved.Set(); // Wake up anybody waiting for empty queue
Wait();
delete m_pWorldGenerator;
@@ -109,6 +110,30 @@ void cChunkGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkGenerator::WaitForQueueEmpty(void)
+{
+ cCSLock Lock(m_CS);
+ while (!mShouldTerminate && !m_Queue.empty())
+ {
+ cCSUnlock Unlock(Lock);
+ m_evtRemoved.Wait();
+ }
+}
+
+
+
+
+
+int cChunkGenerator::GetQueueLength(void)
+{
+ cCSLock Lock(m_CS);
+ return (int)m_Queue.size();
+}
+
+
+
+
+
void cChunkGenerator::Execute(void)
{
while (!mShouldTerminate)
@@ -128,6 +153,7 @@ void cChunkGenerator::Execute(void)
m_Queue.erase( m_Queue.begin() ); // Remove coordinate from queue
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
Lock.Unlock(); // Unlock ASAP
+ m_evtRemoved.Set();
if (
m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ) ||
@@ -138,7 +164,7 @@ void cChunkGenerator::Execute(void)
continue;
}
- LOG("Generating chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
+ LOGD("Generating chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
DoGenerate(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
// Save the chunk right after generating, so that we don't have to generate it again on next run
@@ -151,9 +177,11 @@ void cChunkGenerator::Execute(void)
void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- // TODO: Convert this not to require the actual cChunkPtr (generate into raw char array)
- // char BlockData[cChunk::c_BlockDataSize];
- m_pWorldGenerator->GenerateChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
+ char BlockData[cChunk::c_BlockDataSize];
+ cEntityList Entities;
+ cBlockEntityList BlockEntities;
+ m_pWorldGenerator->GenerateChunk(a_ChunkX, a_ChunkY, a_ChunkZ, BlockData, Entities, BlockEntities);
+ m_World->ChunkDataGenerated(a_ChunkX, a_ChunkY, a_ChunkZ, BlockData, Entities, BlockEntities);
}
diff --git a/source/cChunkGenerator.h b/source/cChunkGenerator.h
index 8b0efc9e8..cb30636c3 100644
--- a/source/cChunkGenerator.h
+++ b/source/cChunkGenerator.h
@@ -43,6 +43,10 @@ public:
void Stop(void);
void GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Queues the chunk for generation; removes duplicate requests
+
+ void WaitForQueueEmpty(void);
+
+ int GetQueueLength(void);
private:
@@ -52,6 +56,7 @@ private:
cCriticalSection m_CS;
cChunkCoordsList m_Queue;
cEvent m_Event; // Set when an item is added to the queue or the thread should terminate
+ cEvent m_evtRemoved; // Set when an item is removed from the queue
// cIsThread override:
virtual void Execute(void) override;
diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp
index 7adaebf90..96d3b14e0 100644
--- a/source/cChunkMap.cpp
+++ b/source/cChunkMap.cpp
@@ -235,7 +235,7 @@ void cChunkMap::ChunkDataLoaded(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const
-void cChunkMap::SetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
+void cChunkMap::ChunkDataGenerated(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
{
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
@@ -244,6 +244,12 @@ void cChunkMap::SetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const cha
return;
}
Chunk->SetAllData(a_BlockData, a_Entities, a_BlockEntities);
+
+ // TODO: This has to go - lighting takes way too long to execute in a locked ChunkMap!
+ Chunk->CalculateLighting();
+
+ Chunk->SetValid();
+ Chunk->MarkDirty();
}
@@ -287,6 +293,48 @@ bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkMap::SpreadChunkLighting(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
+ if ((Chunk != NULL) && Chunk->IsValid())
+ {
+ // TODO: Rewrite this to call Chunk's lighting without any parameters
+ Chunk->SpreadLight( Chunk->pGetSkyLight() );
+ Chunk->SpreadLight( Chunk->pGetLight() );
+ }
+}
+
+
+
+
+
+int cChunkMap::GetHeight(int a_BlockX, int a_BlockZ)
+{
+ cCSLock Lock(m_CSLayers);
+ int ChunkX, ChunkZ, BlockY = 0;
+ AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if (Chunk == NULL)
+ {
+ return 0;
+ }
+
+ // Wait for the chunk to become valid:
+ while (!Chunk->IsValid())
+ {
+ GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ); // Re-queue (in case it managed to get unloaded before we caught it
+ cCSUnlock Unlock(Lock);
+ m_evtChunkValid.Wait();
+ }
+
+ return Chunk->GetHeight(a_BlockX, a_BlockZ);
+}
+
+
+
+
+
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
{
cCSLock Lock(m_CSLayers);
@@ -445,3 +493,12 @@ int cChunkMap::GetNumChunks(void)
+
+void cChunkMap::ChunkValidated(void)
+{
+ m_evtChunkValid.Set();
+}
+
+
+
+
diff --git a/source/cChunkMap.h b/source/cChunkMap.h
index 4ec7ef01d..ffea1d504 100644
--- a/source/cChunkMap.h
+++ b/source/cChunkMap.h
@@ -36,14 +36,16 @@ public:
void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL);
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // a_Player rclked block entity at the coords specified, handle it
- void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
- void SetChunkData (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);
- bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void MarkChunkDirty (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ 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);
+ 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);
+ int GetHeight (int a_BlockX, int a_BlockZ);
void Tick( float a_Dt, MTRand & a_TickRand );
@@ -79,7 +81,7 @@ public:
}
}
-
+ void ChunkValidated(void); // Called by chunks that have become valid
private:
@@ -120,6 +122,7 @@ private:
cCriticalSection m_CSLayers;
cChunkLayerList m_Layers;
+ cEvent m_evtChunkValid; // Set whenever any chunk becomes valid, via ChunkValidated()
cWorld * m_World;
};
diff --git a/source/cPluginManager.cpp b/source/cPluginManager.cpp
index fd1a093d7..1aeb0eb2f 100644
--- a/source/cPluginManager.cpp
+++ b/source/cPluginManager.cpp
@@ -10,7 +10,6 @@
#include "cRoot.h"
#include "cLuaCommandBinder.h"
#include "../iniFile/iniFile.h"
-#include <stdarg.h>
#include "SquirrelBindings.h"
#if USE_SQUIRREL
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index 744780242..f57c8b5cf 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -91,6 +91,55 @@ inline float fRadRand( float a_Radius )
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cWorldLoadProgress:
+
+/// A simple thread that displays the progress of world loading / saving in cWorld::InitializeSpawn()
+class cWorldLoadProgress :
+ public cIsThread
+{
+public:
+ cWorldLoadProgress(cWorld * a_World) :
+ cIsThread("cWorldLoadProgress"),
+ m_World(a_World)
+ {
+ Start();
+ }
+
+protected:
+
+ cWorld * m_World;
+
+ virtual void Execute(void) override
+ {
+ for (;;)
+ {
+ LOG("%d chunks to load, %d chunks to generate",
+ m_World->GetStorage().GetLoadQueueLength(),
+ m_World->GetGenerator().GetQueueLength()
+ );
+
+ // Wait for 2 sec, but be "reasonably wakeable" when the thread is to finish
+ for (int i = 0; i < 20; i++)
+ {
+ cSleep::MilliSleep(100);
+ if (mShouldTerminate)
+ {
+ return;
+ }
+ }
+ } // for (-ever)
+ }
+
+} ;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cWorld:
+
cWorld* cWorld::GetWorld()
{
LOGWARN("WARNING: Using deprecated function cWorld::GetWorld() use cRoot::Get()->GetWorld() instead!");
@@ -154,7 +203,7 @@ cWorld::cWorld( const AString & a_WorldName )
m_GameMode = 0;
AString GeneratorName;
- AString StorageSchema;
+ AString StorageSchema("Default");
cIniFile IniFile( m_WorldName + "/world.ini");
if( IniFile.ReadFile() )
@@ -164,8 +213,8 @@ cWorld::cWorld( const AString & a_WorldName )
m_SpawnZ = IniFile.GetValueF("SpawnPosition", "Z", m_SpawnZ );
m_WorldSeed = IniFile.GetValueI("Seed", "Seed", m_WorldSeed );
m_GameMode = IniFile.GetValueI("GameMode", "GameMode", m_GameMode );
- GeneratorName = IniFile.GetValue("Generator", "GeneratorName", "Default");
- StorageSchema = IniFile.GetValue("Storage", "Schema", "Default");
+ GeneratorName = IniFile.GetValue("Generator", "GeneratorName", GeneratorName);
+ StorageSchema = IniFile.GetValue("Storage", "Schema", StorageSchema);
}
else
{
@@ -174,7 +223,8 @@ cWorld::cWorld( const AString & a_WorldName )
IniFile.SetValueF("SpawnPosition", "Z", m_SpawnZ );
IniFile.SetValueI("Seed", "Seed", m_WorldSeed );
IniFile.SetValueI("GameMode", "GameMode", m_GameMode );
- IniFile.SetValue("Generator", "GeneratorName", "Default" );
+ IniFile.SetValue("Generator", "GeneratorName", GeneratorName);
+ IniFile.SetValue("Storage", "Schema", StorageSchema);
if( !IniFile.WriteFile() )
{
LOG("WARNING: Could not write to %s/world.ini", a_WorldName.c_str());
@@ -380,7 +430,9 @@ void cWorld::InitializeSpawn()
{
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
BlockToChunk( (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ, ChunkX, ChunkY, ChunkZ );
+
int ViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
+
LOG("Preparing spawn area in world \"%s\"", m_WorldName.c_str());
for (int x = 0; x < ViewDist; x++)
{
@@ -390,7 +442,16 @@ void cWorld::InitializeSpawn()
}
}
- // TODO: Wait for the generator to finish generating these chunks
+ // Display progress during this process:
+ cWorldLoadProgress Progress(this);
+
+ // Wait for the loader to finish loading
+ m_Storage.WaitForQueuesEmpty();
+
+ // Wait for the generator to finish generating
+ m_Generator.WaitForQueueEmpty();
+
+ m_SpawnY = (double)GetHeight( (int)m_SpawnX, (int)m_SpawnZ ) + 1.6f; // +1.6f eye height
}
@@ -434,23 +495,7 @@ void cWorld::Tick(float a_Dt)
}
}
- {
- cCSLock Lock(m_CSLighting);
- if (m_SpreadQueue.size() >= 50 )
- {
- LOGWARN("cWorld: Lots of lighting to do! Still %i chunks left!", m_SpreadQueue.size() );
- }
- int TimesSpreaded = 0;
- while ( !m_SpreadQueue.empty() && TimesSpreaded < MAX_LIGHTING_SPREAD_PER_TICK ) // Do not choke the tick thread
- {
- cChunkPtr & Chunk = *m_SpreadQueue.begin();
- //LOG("Spreading: %p", Chunk );
- Chunk->SpreadLight( Chunk->pGetSkyLight() );
- Chunk->SpreadLight( Chunk->pGetLight() );
- m_SpreadQueue.pop_front();
- TimesSpreaded++;
- }
- }
+ TickLighting();
m_ChunkMap->Tick(a_Dt, m_TickRand);
@@ -602,7 +647,7 @@ void cWorld::TickSpawnMobs(float a_Dt)
int nightRand = m_TickRand.randInt() % 10;
SpawnPos += Vector3d( (double)(m_TickRand.randInt() % 64) - 32, (double)(m_TickRand.randInt() % 64) - 32, (double)(m_TickRand.randInt() % 64) - 32 );
- char Height = GetHeight( (int)SpawnPos.x, (int)SpawnPos.z );
+ int Height = GetHeight( (int)SpawnPos.x, (int)SpawnPos.z );
if (m_WorldTime >= 12000 + 1000)
{
@@ -657,6 +702,37 @@ void cWorld::TickSpawnMobs(float a_Dt)
+void cWorld::TickLighting(void)
+{
+ // To avoid a deadlock, we lock the spread queue only long enough to pick the chunk coords to spread
+ // The spreading itself will run unlocked
+ cChunkCoordsList SpreadQueue;
+ {
+ cCSLock Lock(m_CSLighting);
+ if (m_SpreadQueue.size() == 0)
+ {
+ return;
+ }
+ if (m_SpreadQueue.size() >= MAX_LIGHTING_SPREAD_PER_TICK )
+ {
+ LOGWARN("cWorld: Lots of lighting to do! Still %i chunks left!", m_SpreadQueue.size() );
+ }
+ // Move up to MAX_LIGHTING_SPREAD_PER_TICK elements from m_SpreadQueue out into SpreadQueue:
+ cChunkCoordsList::iterator itr = m_SpreadQueue.begin();
+ std::advance(itr, MIN(m_SpreadQueue.size(), MAX_LIGHTING_SPREAD_PER_TICK));
+ SpreadQueue.splice(SpreadQueue.begin(), m_SpreadQueue, m_SpreadQueue.begin(), itr);
+ }
+
+ for (cChunkCoordsList::iterator itr = SpreadQueue.begin(); itr != SpreadQueue.end(); ++itr)
+ {
+ m_ChunkMap->SpreadChunkLighting(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ }
+}
+
+
+
+
+
void cWorld::GrowTree( int a_X, int a_Y, int a_Z )
{
// new tree code, looks much better
@@ -896,16 +972,9 @@ cBlockEntity * cWorld::GetBlockEntity( int a_X, int a_Y, int a_Z )
-char cWorld::GetHeight( int a_X, int a_Z )
+int 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 );
- cChunkPtr Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
- if ( Chunk->IsValid())
- {
- return Chunk->GetHeight( PosX, PosZ );
- }
- return 0;
+ return m_ChunkMap->GetHeight(a_X, a_Z);
}
@@ -914,7 +983,6 @@ char cWorld::GetHeight( int a_X, int a_Z )
const double & cWorld::GetSpawnY(void)
{
- m_SpawnY = (double)GetHeight( (int)m_SpawnX, (int)m_SpawnZ ) + 1.6f; // +1.6f eye height
return m_SpawnY;
}
@@ -983,9 +1051,9 @@ void cWorld::ChunkDataLoaded(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const cha
-void cWorld::SetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
+void cWorld::ChunkDataGenerated(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
{
- m_ChunkMap->SetChunkData(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData, a_Entities, a_BlockEntities);
+ m_ChunkMap->ChunkDataGenerated(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData, a_Entities, a_BlockEntities);
}
@@ -1217,21 +1285,21 @@ void cWorld::SaveAllChunks()
-void cWorld::ReSpreadLighting( const cChunkPtr & a_Chunk )
+void cWorld::ReSpreadLighting(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSLighting);
- m_SpreadQueue.remove( a_Chunk );
- m_SpreadQueue.push_back( a_Chunk );
+ m_SpreadQueue.remove(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ m_SpreadQueue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
}
-void cWorld::RemoveSpread( const cChunkPtr & a_Chunk )
+void cWorld::RemoveSpread(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSLighting);
- m_SpreadQueue.remove( a_Chunk );
+ m_SpreadQueue.remove(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
}
diff --git a/source/cWorld.h b/source/cWorld.h
index 19051bbe1..131361d21 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -60,7 +60,7 @@ public:
cChunkPtr GetChunk ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) {return m_ChunkMap->GetChunk (a_ChunkX, a_ChunkY, a_ChunkZ); }
cChunkPtr GetChunkNoGen ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) {return m_ChunkMap->GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ); }
cChunkPtr GetChunkOfBlock( int a_X, int a_Y, int a_Z );
- char GetHeight( int a_X, int a_Z ); //tolua_export
+ int GetHeight( int a_X, int a_Z ); //tolua_export
//void AddClient( cClientHandle* a_Client );
//void RemoveClient( cClientHandle* a_Client );
@@ -74,7 +74,7 @@ public:
void MarkChunkSaving (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
void MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
- void SetChunkData (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);
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
@@ -165,8 +165,8 @@ public:
void Tick(float a_Dt);
- void ReSpreadLighting(const cChunkPtr & a_Chunk );
- void RemoveSpread(const cChunkPtr & a_Chunk );
+ void ReSpreadLighting(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void RemoveSpread(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
void InitializeSpawn();
@@ -176,6 +176,7 @@ public:
cChunkGenerator & GetGenerator(void) { return m_Generator; }
cWorldStorage & GetStorage (void) { return m_Storage; }
+ cChunkMap * GetChunkMap (void) { return m_ChunkMap; }
private:
@@ -247,7 +248,7 @@ private:
cPlayerList m_Players;
cCriticalSection m_CSLighting;
- cChunkPtrList m_SpreadQueue;
+ cChunkCoordsList m_SpreadQueue;
cCriticalSection m_CSFastSetBlock;
FastSetBlockList m_FastSetBlockQueue;
@@ -261,6 +262,7 @@ private:
void TickWeather(float a_Dt); // Handles weather each tick
void TickSpawnMobs(float a_Dt); // Handles mob spawning each tick
+ void TickLighting(void); // Handles lighting re-spreading
void RemoveEntity( cEntity * a_Entity );
}; //tolua_export
diff --git a/source/cWorldGenerator.cpp b/source/cWorldGenerator.cpp
index fcbbcdad3..284b4c478 100644
--- a/source/cWorldGenerator.cpp
+++ b/source/cWorldGenerator.cpp
@@ -31,19 +31,9 @@ cWorldGenerator::~cWorldGenerator()
-void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities)
{
- // TODO: use a raw char array instead of the entire chunk, then set it as chunk's blockdata
-
- cChunkPtr Chunk = m_World->GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
- assert(!Chunk->IsValid());
-
- memset(Chunk->pGetBlockData(), 0, cChunk::c_BlockDataSize);
- GenerateTerrain(Chunk);
- GenerateFoliage(Chunk);
- Chunk->CalculateHeightmap();
- Chunk->CalculateLighting();
- Chunk->SetValid();
+ GenerateTerrain(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData);
}
@@ -101,40 +91,44 @@ static float GetOreNoise( float x, float y, float z, cNoise & a_Noise )
-void cWorldGenerator::GenerateTerrain( cChunkPtr a_Chunk )
+unsigned int cWorldGenerator::MakeIndex(int x, int y, int z )
{
- Vector3i ChunkPos( a_Chunk->GetPosX(), a_Chunk->GetPosY(), a_Chunk->GetPosZ() );
- char* BlockType = a_Chunk->pGetType();
+ assert((x < 16) && (x > -1) && (y < 128) && (y > -1) && (z < 16) && (z > -1));
- //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;
- const ENUM_BLOCK_ID SandStoneID = E_BLOCK_SANDSTONE;
- const ENUM_BLOCK_ID CaveID = E_BLOCK_AIR;
- const ENUM_BLOCK_ID LavaID = E_BLOCK_STATIONARY_LAVA;
- const ENUM_BLOCK_ID CoalID = E_BLOCK_COAL_ORE;
- const ENUM_BLOCK_ID IronID = E_BLOCK_IRON_ORE;
- const ENUM_BLOCK_ID GoldID = E_BLOCK_GOLD_ORE;
- const ENUM_BLOCK_ID DiamondID = E_BLOCK_DIAMOND_ORE;
- const ENUM_BLOCK_ID RedID = E_BLOCK_REDSTONE_ORE;
-
- cNoise Noise( a_Chunk->GetWorld()->GetWorldSeed() );
- for(int z = 0; z < 16; z++)
+ return y + (z * 128) + (x * 128 * 16);
+}
+
+
+
+
+
+void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData)
+{
+ const int WATER_LEVEL = 60;
+ const int SAND_LEVEL = 3;
+
+ memset(a_BlockData, E_BLOCK_AIR, cChunk::c_BlockDataSize);
+
+ cNoise Noise(m_World->GetWorldSeed());
+
+ for (int z = 0; z < 16; z++)
{
- const float zz = (float)(ChunkPos.z*16 + z);
- for(int x = 0; x < 16; x++)
+ const float zz = (float)(a_ChunkZ * 16 + z);
+ for (int x = 0; x < 16; x++)
{
// Place bedrock on bottom layer
- BlockType[ cChunk::MakeIndex(x, 0, z) ] = E_BLOCK_BEDROCK;
+ a_BlockData[MakeIndex(x, 0, z)] = E_BLOCK_BEDROCK;
- const float xx = (float)(ChunkPos.x*16 + x);
+ const float xx = (float)(a_ChunkX * 16 + x);
- int Height = (int)(GetNoise( xx*0.05f, zz*0.05f, Noise )*16);
+ int Height = (int)(GetNoise( xx * 0.05f, zz * 0.05f, Noise ) * 16);
const int Lower = 64;
- if( Height+Lower > 127 ) Height = 127-Lower;
- const int Top = Lower+Height;
- const float WaveNoise = 1;//m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f ) + 0.5f;
+ if ( Height + Lower > 127 )
+ {
+ Height = 127 - Lower;
+ }
+ const int Top = Lower + Height;
+ const float WaveNoise = 1; // m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f ) + 0.5f;
for( int y = 1; y < Top; ++y )
{
const float yy = (float)y;
@@ -143,42 +137,69 @@ void cWorldGenerator::GenerateTerrain( cChunkPtr a_Chunk )
{
if( y > 4 )
{
- BlockType[ cChunk::MakeIndex(x, y, z) ] = CaveID;
- if( z > 0 ) BlockType[ cChunk::MakeIndex(x, y, z-1) ] = CaveID;
- if( z < 15 ) BlockType[ cChunk::MakeIndex(x, y, z+1) ] = CaveID;
- if( x > 0 ) BlockType[ cChunk::MakeIndex(x-1, y, z) ] = CaveID;
- if( x < 15 ) BlockType[ cChunk::MakeIndex(x+1, y, z) ] = CaveID;
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_AIR;
+ if( z > 0 ) a_BlockData[ MakeIndex(x, y, z-1) ] = E_BLOCK_AIR;
+ if( z < 15 ) a_BlockData[ MakeIndex(x, y, z+1) ] = E_BLOCK_AIR;
+ if( x > 0 ) a_BlockData[ MakeIndex(x-1, y, z) ] = E_BLOCK_AIR;
+ if( x < 15 ) a_BlockData[ MakeIndex(x+1, y, z) ] = E_BLOCK_AIR;
}
else
{
- BlockType[ cChunk::MakeIndex(x, y, z) ] = LavaID;
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_LAVA;
}
}
- else if( y < 61 && Top - y < 3 )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = SandID;
- else if( y < 61 && Top - y < 4 )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = SandStoneID;
- else if( Top - y > ((WaveNoise+1.5f)*1.5f) ) // rock and ores between 1.5 .. 4.5 deep
+ else if ((y < 61) && (Top - y < SAND_LEVEL ))
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SAND;
+ }
+ else if ((y < 61) && (Top - y < 4 ))
{
- if( GetOreNoise( xx, yy, zz, Noise ) > 0.5f )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = CoalID;
- else if( GetOreNoise( xx, yy+100.f, zz, Noise ) > 0.6f )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = IronID;
- else if( yy < 20 && GetOreNoise( xx*1.5f, yy+300.f, zz*1.5f, Noise ) > 0.6f )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = RedID;
- else if( yy < 30 && GetOreNoise( xx*2, yy+200.f, zz*2, Noise ) > 0.75f )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = DiamondID;
- else if( yy < 40 && GetOreNoise( xx*2, yy+100.f, zz*2, Noise ) > 0.75f )
- BlockType[ cChunk::MakeIndex(x, y, z) ] = GoldID;
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SANDSTONE;
+ }
+ else if (Top - y > ((WaveNoise + 1.5f) * 1.5f)) // rock and ores between 1.5 .. 4.5 deep
+ {
+ if ( GetOreNoise( xx, yy, zz, Noise ) > 0.5f )
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_COAL_ORE;
+ }
+ else if ( GetOreNoise( xx, yy+100.f, zz, Noise ) > 0.6f )
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_IRON_ORE;
+ }
+ else if (( yy < 20) && (GetOreNoise( xx * 1.5f, yy + 300.f, zz * 1.5f, Noise ) > 0.6f ))
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_REDSTONE_ORE;
+ }
+ else if (( yy < 30) && (GetOreNoise( xx * 2, yy + 200.f, zz * 2, Noise ) > 0.75f ))
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIAMOND_ORE;
+ }
+ else if (( yy < 40) && (GetOreNoise( xx * 2, yy + 100.f, zz * 2, Noise ) > 0.75f ))
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_GOLD_ORE;
+ }
else
- BlockType[ cChunk::MakeIndex(x, y, z) ] = StoneID;
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STONE;
+ }
}
else
- BlockType[ cChunk::MakeIndex(x, y, z) ] = DirtID;
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIRT;
+ }
+ }
+ if (Top + 1 >= WATER_LEVEL + SAND_LEVEL)
+ {
+ // Replace top dirt with grass:
+ a_BlockData[MakeIndex(x, Top - 1, z)] = E_BLOCK_GRASS;
}
- for( int y = Lower+Height; y < 60; ++y )
+ else
{
- BlockType[ cChunk::MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER;
+ // Add water up to the WATER_LEVEL:
+ for (int y = Top; y < WATER_LEVEL; ++y )
+ {
+ a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER;
+ }
}
}
}
@@ -188,7 +209,7 @@ void cWorldGenerator::GenerateTerrain( cChunkPtr a_Chunk )
-void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk )
+void cWorldGenerator::GenerateFoliage( cChunkPtr & a_Chunk )
{
const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS;
const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT;
@@ -209,7 +230,7 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk )
int TopY = -1;
for(int y = 127; y > 0; y--)
{
- int index = cChunk::MakeIndex( x, y, z );
+ int index = MakeIndex( x, y, z );
if( BlockType[index] != E_BLOCK_AIR )
{
TopY = y;
@@ -219,12 +240,12 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk )
if( TopY > 0 )
{
// Change top dirt into grass and prevent sand from floating over caves
- int index = cChunk::MakeIndex( x, TopY, z );
- int index1 = cChunk::MakeIndex( x, TopY-1, z );
- int index2 = cChunk::MakeIndex( x, TopY-2, z );
- int index3 = cChunk::MakeIndex( x, TopY-3, z );
- int index4 = cChunk::MakeIndex( x, TopY-4, z );
- int index5 = cChunk::MakeIndex( x, TopY-5, z );
+ int index = MakeIndex( x, TopY, z );
+ int index1 = MakeIndex( x, TopY-1, z );
+ int index2 = MakeIndex( x, TopY-2, z );
+ int index3 = MakeIndex( x, TopY-3, z );
+ int index4 = MakeIndex( x, TopY-4, z );
+ int index5 = MakeIndex( x, TopY-5, z );
if( BlockType[index] == SandID ) {
@@ -258,10 +279,10 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk )
{
if( (val1 + val2 > 0.f) && (r1.randInt()%128) > 124 && BlockType[index] == E_BLOCK_SAND )
{
- BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS;
+ BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS;
if( (r1.randInt() & 3) == 3 )
{
- BlockType[ cChunk::MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS;
+ BlockType[ MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS;
}
continue;
}
@@ -273,13 +294,13 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk )
if( val1 + val2 > 0.2f && (r1.randInt()%128) > 124 )
World->GrowTree( xx, TopY, zz );
else if( val3 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER;
+ BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER;
else if( val4 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE;
+ BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE;
else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM;
+ BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM;
else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM;
+ BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM;
}
}
diff --git a/source/cWorldGenerator.h b/source/cWorldGenerator.h
index 208178d4a..92c2a1d0c 100644
--- a/source/cWorldGenerator.h
+++ b/source/cWorldGenerator.h
@@ -18,7 +18,7 @@ public:
cWorldGenerator(cWorld * a_World);
~cWorldGenerator();
- virtual void GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ virtual void GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
protected:
@@ -27,8 +27,11 @@ protected:
// Thread-unsafe:
MTRand r1;
- virtual void GenerateTerrain( cChunkPtr a_Chunk );
- virtual void GenerateFoliage( cChunkPtr a_Chunk );
+ static unsigned int MakeIndex(int x, int y, int z );
+
+ virtual void GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData);
+
+ virtual void GenerateFoliage(cChunkPtr & a_Chunk );
};
diff --git a/source/cWorldGenerator_Test.cpp b/source/cWorldGenerator_Test.cpp
index 08e649fb9..1ffcdbfbe 100644
--- a/source/cWorldGenerator_Test.cpp
+++ b/source/cWorldGenerator_Test.cpp
@@ -9,24 +9,27 @@
-void cWorldGenerator_Test::GenerateTerrain( cChunkPtr a_Chunk )
+void cWorldGenerator_Test::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData)
{
- char* BlockType = a_Chunk->pGetType();
-
+ memset(a_BlockData, E_BLOCK_DIRT, cChunk::c_NumBlocks);
for(int x = 0; x < 16; x++)
{
for(int z = 0; z < 16; z++)
{
- for( int y = 1; y < 128; ++y )
- {
- unsigned int idx = cChunk::MakeIndex(x, y, z);
- BlockType[idx] = E_BLOCK_DIRT;
- }
+ a_BlockData[MakeIndex(x, 0, z)] = E_BLOCK_BEDROCK;
}
}
}
-void cWorldGenerator_Test::GenerateFoliage( cChunkPtr a_Chunk )
+
+
+
+
+void cWorldGenerator_Test::GenerateFoliage( cChunkPtr & a_Chunk )
{
(void)a_Chunk;
-} \ No newline at end of file
+}
+
+
+
+
diff --git a/source/cWorldGenerator_Test.h b/source/cWorldGenerator_Test.h
index 5a5483fa9..8c4dc0e99 100644
--- a/source/cWorldGenerator_Test.h
+++ b/source/cWorldGenerator_Test.h
@@ -15,8 +15,9 @@ public:
cWorldGenerator_Test(cWorld * a_World) : cWorldGenerator(a_World) {}
protected:
- virtual void GenerateTerrain( cChunkPtr a_Chunk ) override;
- virtual void GenerateFoliage( cChunkPtr a_Chunk ) override;
+
+ virtual void GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData) override;
+ virtual void GenerateFoliage(cChunkPtr & a_Chunk ) override;
};