diff options
Diffstat (limited to '')
-rw-r--r-- | source/cWorld.cpp | 492 |
1 files changed, 258 insertions, 234 deletions
diff --git a/source/cWorld.cpp b/source/cWorld.cpp index a2c651d44..9abfb963e 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -36,12 +36,11 @@ #include "cCavespider.h" //cavespider
#include "cGhast.h" //Ghast
#include "cZombiepigman.h" //Zombiepigman
-#include "cGenSettings.h"
#include "cMakeDir.h"
#include "cChunkGenerator.h"
#include "MersenneTwister.h"
-#include "cWorldGenerator_Test.h"
#include "cTracer.h"
+#include "Trees.h"
#include "packets/cPacket_TimeUpdate.h"
@@ -71,12 +70,6 @@ const int MAX_LIGHTING_SPREAD_PER_TICK = 10; float cWorld::m_Time = 0.f;
-char g_BlockLightValue[128];
-char g_BlockSpreadLightFalloff[128];
-bool g_BlockTransparent[128];
-bool g_BlockOneHitDig[128];
-bool g_BlockPistonBreakable[128];
-
@@ -96,6 +89,12 @@ public: Start();
}
+ void Stop(void)
+ {
+ m_ShouldTerminate = true;
+ Wait();
+ }
+
protected:
cWorld * m_World;
@@ -127,6 +126,53 @@ protected: +/// A simple thread that displays the progress of world lighting in cWorld::InitializeSpawn()
+class cWorldLightingProgress :
+ public cIsThread
+{
+public:
+ cWorldLightingProgress(cLightingThread * a_Lighting) :
+ cIsThread("cWorldLightingProgress"),
+ m_Lighting(a_Lighting)
+ {
+ Start();
+ }
+
+ void Stop(void)
+ {
+ m_ShouldTerminate = true;
+ Wait();
+ }
+
+protected:
+
+ cLightingThread * m_Lighting;
+
+ virtual void Execute(void) override
+ {
+ for (;;)
+ {
+ LOG("%d chunks remaining to light", m_Lighting->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 (m_ShouldTerminate)
+ {
+ return;
+ }
+ }
+ } // for (-ever)
+ }
+
+} ;
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cWorld:
@@ -182,21 +228,6 @@ cWorld::cWorld( const AString & a_WorldName ) , m_RSList ( 0 )
, m_Weather ( eWeather_Sunny )
{
- /*
- // DEBUG:
- DWORD Tick = GetTickCount();
- for (int i = 0; i < 3000; i++)
- {
- BLOCKTYPE Playground[cChunkDef::NumBlocks / 2];
- for (int x = 0; x < 16; x++) for (int z = 0; z < 16; z++) for (int y = 0; y < 256; y++)
- {
- cChunkDef::SetNibble(Playground, x, y, z, x);
- } // for x, y, z
- } // for i
- Tick = GetTickCount() - Tick;
- LOGINFO("3000 chunkfulls of SetNibble() took %d ticks", Tick);
- //*/
-
LOG("cWorld::cWorld(%s)", a_WorldName.c_str());
m_WorldName = a_WorldName;
m_IniFileName = m_WorldName + "/world.ini";
@@ -207,10 +238,8 @@ cWorld::cWorld( const AString & a_WorldName ) m_SpawnX = (double)((r1.randInt()%1000)-500);
m_SpawnY = cChunkDef::Height;
m_SpawnZ = (double)((r1.randInt()%1000)-500);
- m_WorldSeed = r1.randInt();
m_GameMode = eGameMode_Creative;
- AString GeneratorName;
AString StorageSchema("Default");
cIniFile IniFile(m_IniFileName);
@@ -219,9 +248,7 @@ cWorld::cWorld( const AString & a_WorldName ) m_SpawnX = IniFile.GetValueF("SpawnPosition", "X", m_SpawnX );
m_SpawnY = IniFile.GetValueF("SpawnPosition", "Y", m_SpawnY );
m_SpawnZ = IniFile.GetValueF("SpawnPosition", "Z", m_SpawnZ );
- m_WorldSeed = IniFile.GetValueI("Seed", "Seed", m_WorldSeed );
m_GameMode = (eGameMode)IniFile.GetValueI("GameMode", "GameMode", m_GameMode );
- GeneratorName = IniFile.GetValue("Generator", "GeneratorName", GeneratorName);
StorageSchema = IniFile.GetValue("Storage", "Schema", StorageSchema);
}
else
@@ -229,19 +256,17 @@ cWorld::cWorld( const AString & a_WorldName ) IniFile.SetValueF("SpawnPosition", "X", m_SpawnX );
IniFile.SetValueF("SpawnPosition", "Y", m_SpawnY );
IniFile.SetValueF("SpawnPosition", "Z", m_SpawnZ );
- IniFile.SetValueI("Seed", "Seed", m_WorldSeed );
IniFile.SetValueI("GameMode", "GameMode", m_GameMode );
- IniFile.SetValue("Generator", "GeneratorName", GeneratorName);
IniFile.SetValue("Storage", "Schema", StorageSchema);
if( !IniFile.WriteFile() )
{
LOG("WARNING: Could not write to %s", m_IniFileName.c_str());
}
}
- LOGINFO("Seed: %i", m_WorldSeed );
-
+
+ m_Lighting.Start(this);
m_Storage.Start(this, StorageSchema);
- m_Generator.Start(this, GeneratorName);
+ m_Generator.Start(this, IniFile);
m_bAnimals = true;
m_SpawnMonsterRate = 10;
@@ -277,105 +302,6 @@ cWorld::cWorld( const AString & a_WorldName ) m_SimulatorManager->RegisterSimulator(m_SandSimulator, 1);
m_SimulatorManager->RegisterSimulator(m_FireSimulator, 10);
m_SimulatorManager->RegisterSimulator(m_RedstoneSimulator, 1);
-
- memset( g_BlockLightValue, 0x0, sizeof( g_BlockLightValue ) );
- memset( g_BlockSpreadLightFalloff, 0xf, sizeof( g_BlockSpreadLightFalloff ) ); // 0xf means total falloff
- memset( g_BlockTransparent, 0x0, sizeof( g_BlockTransparent ) );
- memset( g_BlockOneHitDig, 0x0, sizeof( g_BlockOneHitDig ) );
- memset( g_BlockPistonBreakable, 0x0, sizeof( g_BlockPistonBreakable ) );
-
- // Emissive blocks
- g_BlockLightValue[ E_BLOCK_TORCH ] = 14;
- g_BlockLightValue[ E_BLOCK_FIRE ] = 15;
- g_BlockLightValue[ E_BLOCK_LAVA ] = 15;
- g_BlockLightValue[ E_BLOCK_STATIONARY_LAVA ] = 15;
- g_BlockLightValue[ E_BLOCK_GLOWSTONE ] = 15;
-
- // Spread blocks
- g_BlockSpreadLightFalloff[ E_BLOCK_AIR ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_TORCH ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_FIRE ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_LAVA ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_STATIONARY_LAVA ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_WATER ] = 4; // Light in water dissapears faster
- g_BlockSpreadLightFalloff[ E_BLOCK_STATIONARY_WATER ] = 4;
- g_BlockSpreadLightFalloff[ E_BLOCK_LEAVES ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_GLASS ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_GLOWSTONE ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_SIGN_POST ] = 1;
- g_BlockSpreadLightFalloff[ E_BLOCK_WALLSIGN ] = 1;
-
- // Transparent blocks
- g_BlockTransparent[ E_BLOCK_AIR ] = true;
- g_BlockTransparent[ E_BLOCK_GLASS ] = true;
- g_BlockTransparent[ E_BLOCK_FIRE ] = true;
- g_BlockTransparent[ E_BLOCK_ICE ] = true;
- g_BlockTransparent[ E_BLOCK_TORCH ] = true;
- g_BlockTransparent[ E_BLOCK_SIGN_POST ] = true;
- g_BlockTransparent[ E_BLOCK_WALLSIGN ] = true;
- g_BlockTransparent[ E_BLOCK_TALL_GRASS ] = true;
- g_BlockTransparent[ E_BLOCK_YELLOW_FLOWER ] = true;
- g_BlockTransparent[ E_BLOCK_RED_ROSE ] = true;
- g_BlockTransparent[ E_BLOCK_RED_MUSHROOM ] = true;
- g_BlockTransparent[ E_BLOCK_BROWN_MUSHROOM ] = true;
- g_BlockTransparent[ E_BLOCK_SNOW ] = true;
-
- // TODO: Any other transparent blocks?
-
- // One hit break blocks
- g_BlockOneHitDig[ E_BLOCK_SAPLING ] = true;
- g_BlockOneHitDig[ E_BLOCK_YELLOW_FLOWER ] = true;
- g_BlockOneHitDig[ E_BLOCK_RED_ROSE ] = true;
- g_BlockOneHitDig[ E_BLOCK_BROWN_MUSHROOM ] = true;
- g_BlockOneHitDig[ E_BLOCK_RED_MUSHROOM ] = true;
- g_BlockOneHitDig[ E_BLOCK_TNT ] = true;
- g_BlockOneHitDig[ E_BLOCK_TORCH ] = true;
- g_BlockOneHitDig[ E_BLOCK_REDSTONE_WIRE ] = true;
- g_BlockOneHitDig[ E_BLOCK_CROPS ] = true;
- g_BlockOneHitDig[ E_BLOCK_REDSTONE_TORCH_OFF ] = true;
- g_BlockOneHitDig[ E_BLOCK_REDSTONE_TORCH_ON ] = true;
- g_BlockOneHitDig[ E_BLOCK_REEDS ] = true;
- g_BlockOneHitDig[ E_BLOCK_REDSTONE_WIRE ] = true;
- g_BlockOneHitDig[ E_BLOCK_REDSTONE_REPEATER_OFF ] = true;
- g_BlockOneHitDig[ E_BLOCK_REDSTONE_REPEATER_ON ] = true;
- g_BlockOneHitDig[ E_BLOCK_LOCKED_CHEST ] = true;
- g_BlockOneHitDig [ E_BLOCK_FIRE ] = true;
-
- // Blocks that breaks when pushed by piston
- g_BlockPistonBreakable[ E_BLOCK_AIR ] = true;
- g_BlockPistonBreakable[ E_BLOCK_STATIONARY_WATER ] = false; //This gave pistons the ability to drop water :D
- g_BlockPistonBreakable[ E_BLOCK_WATER ] = false;
- g_BlockPistonBreakable[ E_BLOCK_STATIONARY_LAVA ] = false;
- g_BlockPistonBreakable[ E_BLOCK_LAVA ] = false;
- g_BlockPistonBreakable[ E_BLOCK_BED ] = true;
- g_BlockPistonBreakable[ E_BLOCK_COBWEB ] = true;
- g_BlockPistonBreakable[ E_BLOCK_TALL_GRASS ] = true;
- g_BlockPistonBreakable[ E_BLOCK_YELLOW_FLOWER ] = true;
- g_BlockPistonBreakable[ E_BLOCK_BROWN_MUSHROOM ] = true;
- g_BlockPistonBreakable[ E_BLOCK_RED_ROSE ] = true;
- g_BlockPistonBreakable[ E_BLOCK_RED_MUSHROOM ] = true;
- g_BlockPistonBreakable[ E_BLOCK_DEAD_BUSH ] = true;
- g_BlockPistonBreakable[ E_BLOCK_TORCH ] = true;
- g_BlockPistonBreakable[ E_BLOCK_FIRE ] = true;
- g_BlockPistonBreakable[ E_BLOCK_REDSTONE_WIRE ] = true;
- g_BlockPistonBreakable[ E_BLOCK_CROPS ] = true;
- g_BlockPistonBreakable[ E_BLOCK_LADDER ] = true;
- g_BlockPistonBreakable[ E_BLOCK_WOODEN_DOOR ] = true;
- g_BlockPistonBreakable[ E_BLOCK_IRON_DOOR ] = true;
- g_BlockPistonBreakable[ E_BLOCK_LEVER ] = true;
- g_BlockPistonBreakable[ E_BLOCK_STONE_BUTTON ] = true;
- g_BlockPistonBreakable[ E_BLOCK_REDSTONE_TORCH_ON ] = true;
- g_BlockPistonBreakable[ E_BLOCK_REDSTONE_TORCH_OFF ]= true;
- g_BlockPistonBreakable[ E_BLOCK_SNOW ] = true;
- g_BlockPistonBreakable[ E_BLOCK_REEDS ] = true;
- g_BlockPistonBreakable[ E_BLOCK_PUMPKIN_STEM ] = true;
- g_BlockPistonBreakable[ E_BLOCK_MELON_STEM ] = true;
- g_BlockPistonBreakable[ E_BLOCK_MELON ] = true;
- g_BlockPistonBreakable[ E_BLOCK_PUMPKIN ] = true;
- g_BlockPistonBreakable[ E_BLOCK_JACK_O_LANTERN ] = true;
- g_BlockPistonBreakable[ E_BLOCK_VINES ] = true;
- g_BlockPistonBreakable[ E_BLOCK_STONE_PRESSURE_PLATE ] = true;
- g_BlockPistonBreakable[ E_BLOCK_WOODEN_PRESSURE_PLATE ] = true;
}
@@ -434,7 +360,7 @@ void cWorld::CastThunderbolt ( int a_X, int a_Y, int a_Z ) -void cWorld::InitializeSpawn()
+void cWorld::InitializeSpawn(void)
{
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
BlockToChunk( (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ, ChunkX, ChunkY, ChunkZ );
@@ -446,24 +372,51 @@ void cWorld::InitializeSpawn() int ViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
#endif // _DEBUG
- LOG("Preparing spawn area in world \"%s\"", m_WorldName.c_str());
+ LOG("Preparing spawn area in world \"%s\"...", m_WorldName.c_str());
for (int x = 0; x < ViewDist; x++)
{
for (int z = 0; z < ViewDist; z++)
{
- m_ChunkMap->TouchChunk( x + ChunkX-(ViewDist - 1) / 2, 0, z + ChunkZ-(ViewDist - 1) / 2 ); // Queue the chunk in the generator / loader
+ m_ChunkMap->TouchChunk( x + ChunkX-(ViewDist - 1) / 2, ZERO_CHUNK_Y, z + ChunkZ-(ViewDist - 1) / 2 ); // Queue the chunk in the generator / loader
}
}
- // Display progress during this process:
- cWorldLoadProgress Progress(this);
+ {
+ // 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();
+
+ Progress.Stop();
+ }
- // Wait for the loader to finish loading
- m_Storage.WaitForQueuesEmpty();
+ // Light all chunks that have been newly generated:
+ LOG("Lighting spawn area in world \"%s\"...", m_WorldName.c_str());
- // Wait for the generator to finish generating
- m_Generator.WaitForQueueEmpty();
+ for (int x = 0; x < ViewDist; x++)
+ {
+ int ChX = x + ChunkX-(ViewDist - 1) / 2;
+ for (int z = 0; z < ViewDist; z++)
+ {
+ int ChZ = z + ChunkZ-(ViewDist - 1) / 2;
+ if (!m_ChunkMap->IsChunkLighted(ChX, ChZ))
+ {
+ m_Lighting.QueueChunk(ChX, ChZ); // Queue the chunk in the lighting thread
+ }
+ } // for z
+ } // for x
+ {
+ cWorldLightingProgress Progress(&m_Lighting);
+ m_Lighting.WaitForQueueEmpty();
+ Progress.Stop();
+ }
+
+ // TODO: Better spawn detection - move spawn out of the water if it isn't set in the INI already
m_SpawnY = (double)GetHeight( (int)m_SpawnX, (int)m_SpawnZ ) + 1.6f; // +1.6f eye height
}
@@ -508,8 +461,6 @@ void cWorld::Tick(float a_Dt) }
}
- TickLighting();
-
m_ChunkMap->Tick(a_Dt, m_TickRand);
GetSimulatorManager()->Simulate(a_Dt);
@@ -523,7 +474,7 @@ void cWorld::Tick(float a_Dt) std::swap(FastSetBlockQueueCopy, m_FastSetBlockQueue);
}
m_ChunkMap->FastSetBlocks(FastSetBlockQueueCopy);
- if (FastSetBlockQueueCopy.size() > 0)
+ if (!FastSetBlockQueueCopy.empty())
{
// Some blocks failed, store them for next tick:
cCSLock Lock(m_CSFastSetBlock);
@@ -716,30 +667,17 @@ void cWorld::TickSpawnMobs(float a_Dt) -void cWorld::TickLighting(void)
+void cWorld::GrowTree( int a_X, int a_Y, int a_Z )
{
- // 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;
+ if (GetBlock(a_X, a_Y, a_Z) == E_BLOCK_SAPLING)
{
- 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);
+ // There is a sapling here, grow a tree according to its type:
+ GrowTreeFromSapling(a_X, a_Y, a_Z, GetBlockMeta(a_X, a_Y, a_Z));
}
-
- for (cChunkCoordsList::iterator itr = SpreadQueue.begin(); itr != SpreadQueue.end(); ++itr)
+ else
{
- m_ChunkMap->SpreadChunkLighting(itr->m_ChunkX, itr->m_ChunkY, itr->m_ChunkZ);
+ // There is nothing here, grow a tree based on the current biome here:
+ GrowTreeByBiome(a_X, a_Y, a_Z);
}
}
@@ -747,73 +685,84 @@ void cWorld::TickLighting(void) -void cWorld::GrowTree( int a_X, int a_Y, int a_Z )
+void cWorld::GrowTreeFromSapling(int a_X, int a_Y, int a_Z, char a_SaplingMeta)
{
- // new tree code, looks much better
- // with help from seanj
- // converted from php to lua then lua to c++
-
- // build trunk
- MTRand r1;
- int trunk = r1.randInt() % (7 - 5 + 1) + 5;
- for (int i = 0; i < trunk; i++)
+ cNoise Noise(m_Generator.GetSeed());
+ sSetBlockVector Blocks;
+ switch (a_SaplingMeta & 0x07)
{
- FastSetBlock( a_X, a_Y + i, a_Z, E_BLOCK_LOG, 0 );
+ case E_META_SAPLING_APPLE: GetAppleTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Blocks); break;
+ case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Blocks); break;
+ case E_META_SAPLING_CONIFER: GetConiferTreeImage(a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Blocks); break;
+ case E_META_SAPLING_JUNGLE: GetJungleTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Blocks); break;
}
+
+ GrowTreeImage(Blocks);
+}
+
+
+
+
+
+void cWorld::GrowTreeByBiome(int a_X, int a_Y, int a_Z)
+{
+ cNoise Noise(m_Generator.GetSeed());
+ sSetBlockVector Blocks;
+ GetTreeImageByBiome(a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), (EMCSBiome)GetBiomeAt(a_X, a_Z), Blocks);
+ GrowTreeImage(Blocks);
+}
- // build tree
- for (int j = 0; j < trunk; j++)
+
+
+
+
+void cWorld::GrowTreeImage(const sSetBlockVector & a_Blocks)
+{
+ // Check that the tree has place to grow
+
+ // Make a copy of the log blocks:
+ sSetBlockVector b2;
+ for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- int radius = trunk - j;
- if (radius < 4)
+ if (itr->BlockType == E_BLOCK_LOG)
{
- if (radius > 2)
- {
- radius = 2;
- }
- for (int i = a_X - radius; i <= a_X + radius; i++)
+ b2.push_back(*itr);
+ }
+ } // for itr - a_Blocks[]
+
+ // Query blocktypes and metas at those log blocks:
+ if (!GetBlocks(b2, false))
+ {
+ return;
+ }
+
+ // Check that at each log's coord there's an block allowed to be overwritten:
+ for (sSetBlockVector::const_iterator itr = b2.begin(); itr != b2.end(); ++itr)
+ {
+ switch (itr->BlockType)
+ {
+ CASE_TREE_ALLOWED_BLOCKS:
{
- for (int k = a_Z-radius; k <= a_Z + radius; k++)
- {
- // small chance to be missing a block to add a little random
- if (k != a_Z || i != a_X && (r1.randInt() % 100 + 1) > 20)
- {
- if( GetBlock( i, a_Y + j, k ) == E_BLOCK_AIR )
- {
- FastSetBlock(i, a_Y+j, k, E_BLOCK_LEAVES, 0 );
- }
- }
- else
- {
- //if( m_BlockType[ MakeIndex(i, TopY+j, k) ] == E_BLOCK_AIR )
- // m_BlockType[ MakeIndex(i, TopY+j, k) ] = E_BLOCK_LEAVES;
- }
- }
+ break;
}
- if (GetBlock( a_X, a_Y+j, a_Z ) == E_BLOCK_AIR )
+ default:
{
- FastSetBlock( a_X, a_Y+j, a_Z, E_BLOCK_LOG, 0 );
+ return;
}
}
- }
-
- // do the top
- if( GetBlock( a_X+1, a_Y+trunk, a_Z ) == E_BLOCK_AIR )
- FastSetBlock( a_X+1, a_Y+trunk, a_Z, E_BLOCK_LEAVES, 0 );
+ } // for itr - b2[]
+
+ // All ok, replace blocks with the tree image:
+ m_ChunkMap->ReplaceTreeBlocks(a_Blocks);
+}
- if( GetBlock( a_X-1, a_Y+trunk, a_Z ) == E_BLOCK_AIR )
- FastSetBlock( a_X-1, a_Y+trunk, a_Z, E_BLOCK_LEAVES, 0 );
- if( GetBlock( a_X, a_Y+trunk, a_Z+1 ) == E_BLOCK_AIR )
- FastSetBlock( a_X, a_Y+trunk, a_Z+1, E_BLOCK_LEAVES, 0 );
- if( GetBlock( a_X, a_Y+trunk, a_Z-1 ) == E_BLOCK_AIR )
- FastSetBlock( a_X, a_Y+trunk, a_Z-1, E_BLOCK_LEAVES, 0 );
- if( GetBlock( a_X, a_Y+trunk, a_Z ) == E_BLOCK_AIR )
- FastSetBlock( a_X, a_Y+trunk, a_Z, E_BLOCK_LEAVES, 0 );
- // end new tree code
+int cWorld::GetBiomeAt (int a_BlockX, int a_BlockZ)
+{
+ return m_ChunkMap->GetBiomeAt(a_BlockX, a_BlockZ);
}
@@ -905,6 +854,24 @@ char cWorld::GetBlockSkyLight( int a_X, int a_Y, int a_Z ) +void cWorld::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType)
+{
+ m_ChunkMap->ReplaceBlocks(a_Blocks, a_FilterBlockType);
+}
+
+
+
+
+
+bool cWorld::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
+{
+ return m_ChunkMap->GetBlocks(a_Blocks, a_ContinueOnFailure);
+}
+
+
+
+
+
bool cWorld::DigBlock( int a_X, int a_Y, int a_Z, cItem & a_PickupItem )
{
bool res = m_ChunkMap->DigBlock(a_X, a_Y, a_Z, a_PickupItem);
@@ -1018,38 +985,58 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkY, int a_ChunkZ) -void cWorld::ChunkDataLoaded(
+void cWorld::SetChunkData(
int a_ChunkX, int a_ChunkY, int a_ChunkZ,
const BLOCKTYPE * a_BlockTypes,
- const BLOCKTYPE * a_BlockMeta,
- const BLOCKTYPE * a_BlockLight,
- const BLOCKTYPE * a_BlockSkyLight,
+ const NIBBLETYPE * a_BlockMeta,
+ const NIBBLETYPE * a_BlockLight,
+ const NIBBLETYPE * a_BlockSkyLight,
const cChunkDef::HeightMap * a_HeightMap,
+ const cChunkDef::BiomeMap * a_BiomeMap,
cEntityList & a_Entities,
- cBlockEntityList & a_BlockEntities
+ cBlockEntityList & a_BlockEntities,
+ bool a_MarkDirty
)
{
- m_ChunkMap->ChunkDataLoaded(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_Entities, a_BlockEntities);
- m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkY, a_ChunkZ);
+ // Validate biomes, if needed:
+ cChunkDef::BiomeMap BiomeMap;
+ const cChunkDef::BiomeMap * Biomes = a_BiomeMap;
+ if (a_BiomeMap == NULL)
+ {
+ // The biomes are not assigned, get them from the generator:
+ Biomes = &BiomeMap;
+ m_Generator.GenerateBiomes(a_ChunkX, a_ChunkZ, BiomeMap);
+ }
+
+ m_ChunkMap->SetChunkData(
+ a_ChunkX, a_ChunkY, a_ChunkZ,
+ a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight,
+ a_HeightMap, *Biomes,
+ a_Entities, a_BlockEntities,
+ a_MarkDirty
+ );
+
+ // If a client is requesting this chunk, send it to them:
+ if (m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkY, a_ChunkZ))
+ {
+ m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkY, a_ChunkZ);
+ }
+
+ // Notify the lighting thread that the chunk has become valid (in case it is a neighbor of a postponed chunk):
+ m_Lighting.ChunkReady(a_ChunkX, a_ChunkZ);
}
-void cWorld::ChunkDataGenerated(
- int a_ChunkX, int a_ChunkY, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const BLOCKTYPE * a_BlockMeta,
- const BLOCKTYPE * a_BlockLight,
- const BLOCKTYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- cEntityList & a_Entities,
- cBlockEntityList & a_BlockEntities
+void cWorld::ChunkLighted(
+ int a_ChunkX, int a_ChunkZ,
+ const cChunkDef::BlockNibbles & a_BlockLight,
+ const cChunkDef::BlockNibbles & a_SkyLight
)
{
- m_ChunkMap->ChunkDataGenerated(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_Entities, a_BlockEntities);
- m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkY, a_ChunkZ);
+ m_ChunkMap->ChunkLighted(a_ChunkX, a_ChunkZ, a_BlockLight, a_SkyLight);
}
@@ -1431,14 +1418,41 @@ void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ) m_ChunkMap->MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
// Trick: use Y=1 to force the chunk generation even though the chunk data is already present
- m_Generator.GenerateChunk(a_ChunkX, 1, a_ChunkZ);
+ m_Generator.QueueGenerateChunk(a_ChunkX, 1, a_ChunkZ);
+}
+
+
+
+
+
+void cWorld::GenerateChunk(int a_ChunkX, int a_ChunkZ)
+{
+ m_Generator.QueueGenerateChunk(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+}
+
+
+
+
+
+void cWorld::QueueLightChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback)
+{
+ m_Lighting.QueueChunk(a_ChunkX, a_ChunkZ, a_Callback);
+}
+
+
+
+
+
+bool cWorld::IsChunkLighted(int a_ChunkX, int a_ChunkZ)
+{
+ return m_ChunkMap->IsChunkLighted(a_ChunkX, a_ChunkZ);
}
-void cWorld::SaveAllChunks()
+void cWorld::SaveAllChunks(void)
{
LOG("Saving all chunks...");
m_LastSave = m_Time;
@@ -1514,3 +1528,13 @@ int cWorld::GetNumChunks(void) const +
+void cWorld::GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue)
+{
+ m_ChunkMap->GetChunkStats(a_NumValid, a_NumDirty);
+ a_NumInLightingQueue = (int) m_Lighting.GetQueueLength();
+}
+
+
+
+
|