1
0

The subgenerators use cChunkDesc instead of raw arrays. cChunkDesc is based on cBlockArea. Initial version of Lakes generator.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1286 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2013-03-19 08:32:02 +00:00
parent 1c1bcf5c07
commit b4697ab9db
11 changed files with 324 additions and 171 deletions

View File

@ -92,6 +92,70 @@ static void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, N
/// Combinator used for cBlockArea::msLake merging
static void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
{
// Sponge is the NOP block
if (a_SrcType == E_BLOCK_SPONGE)
{
return;
}
// Air is always hollowed out
if (a_SrcType == E_BLOCK_AIR)
{
a_DstType = E_BLOCK_AIR;
a_DstMeta = 0;
return;
}
// Water and lava are never overwritten
switch (a_DstType)
{
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_LAVA:
case E_BLOCK_STATIONARY_LAVA:
{
return;
}
}
// Water and lava always overwrite
switch (a_SrcType)
{
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_LAVA:
case E_BLOCK_STATIONARY_LAVA:
{
a_DstType = a_SrcType;
a_DstMeta = a_DstMeta;
return;
}
}
if (a_SrcType == E_BLOCK_STONE)
{
switch (a_DstType)
{
case E_BLOCK_DIRT:
case E_BLOCK_GRASS:
case E_BLOCK_MYCELIUM:
{
a_DstType = E_BLOCK_STONE;
a_DstMeta = 0;
return;
}
}
}
// Everything else is left as it is
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cBlockArea: // cBlockArea:
@ -611,6 +675,21 @@ void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_R
break; break;
} // case msImprint } // case msImprint
case msLake:
{
InternalMergeBlocks(
m_BlockTypes, a_Src.GetBlockTypes(),
DstMetas, SrcMetas,
SizeX, SizeY, SizeZ,
SrcOffX, SrcOffY, SrcOffZ,
DstOffX, DstOffY, DstOffZ,
a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(),
m_SizeX, m_SizeY, m_SizeZ,
MergeCombinatorLake
);
break;
} // case msLake
default: default:
{ {
LOGWARNING("Unknown block area merge strategy: %d", a_Strategy); LOGWARNING("Unknown block area merge strategy: %d", a_Strategy);

View File

@ -49,6 +49,7 @@ public:
msOverwrite, msOverwrite,
msFillAir, msFillAir,
msImprint, msImprint,
msLake,
} ; } ;
cBlockArea(void); cBlockArea(void);
@ -112,6 +113,24 @@ public:
- msOverwrite completely overwrites all blocks with the Src's blocks - msOverwrite completely overwrites all blocks with the Src's blocks
- msFillAir overwrites only those blocks that were air - msFillAir overwrites only those blocks that were air
- msImprint overwrites with only those blocks that are non-air - msImprint overwrites with only those blocks that are non-air
Special strategies:
msLake (evaluate top-down, first match wins):
| area block | |
| this | Src | result |
+----------+--------+--------+
| A | sponge | A | Sponge is the NOP block
| * | air | air | Air always gets hollowed out, even under the oceans
| water | * | water | Water is never overwritten
| lava | * | lava | Lava is never overwritten
| * | water | water | Water always overwrites anything
| * | lava | lava | Lava always overwrites anything
| dirt | stone | stone | Stone overwrites dirt
| grass | stone | stone | ... and grass
| mycelium | stone | stone | ... and mycelium
| A | stone | A | ... but nothing else
| A | * | A | Everything else is left as it is
*/ */
void Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy); void Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy);

View File

@ -20,8 +20,11 @@ cChunkDesc::cChunkDesc(int a_ChunkX, int a_ChunkZ) :
m_bUseDefaultStructures(true), m_bUseDefaultStructures(true),
m_bUseDefaultFinish(true) m_bUseDefaultFinish(true)
{ {
m_BlockArea.Create(cChunkDef::Width, cChunkDef::Height, cChunkDef::Width);
/*
memset(m_BlockTypes, 0, sizeof(cChunkDef::BlockTypes)); memset(m_BlockTypes, 0, sizeof(cChunkDef::BlockTypes));
memset(m_BlockMeta, 0, sizeof(cChunkDef::BlockNibbles)); memset(m_BlockMeta, 0, sizeof(cChunkDef::BlockNibbles));
*/
memset(m_BiomeMap, 0, sizeof(cChunkDef::BiomeMap)); memset(m_BiomeMap, 0, sizeof(cChunkDef::BiomeMap));
memset(m_HeightMap, 0, sizeof(cChunkDef::HeightMap)); memset(m_HeightMap, 0, sizeof(cChunkDef::HeightMap));
} }
@ -51,9 +54,7 @@ void cChunkDesc::SetChunkCoords(int a_ChunkX, int a_ChunkZ)
void cChunkDesc::FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) void cChunkDesc::FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
const NIBBLETYPE CompressedMeta = a_BlockMeta | (a_BlockMeta << 4); m_BlockArea.Fill(cBlockArea::baTypes | cBlockArea::baMetas, a_BlockType, a_BlockMeta);
memset(m_BlockTypes, a_BlockType, sizeof(cChunkDef::BlockTypes));
memset(m_BlockMeta, CompressedMeta, sizeof(cChunkDef::BlockNibbles));
} }
@ -62,9 +63,7 @@ void cChunkDesc::FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
void cChunkDesc::SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) void cChunkDesc::SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
int Index = cChunkDef::MakeIndex(a_RelX, a_RelY, a_RelZ); m_BlockArea.SetRelBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
cChunkDef::SetBlock(m_BlockTypes, Index, a_BlockType);
cChunkDef::SetNibble(m_BlockMeta, Index, a_BlockMeta);
} }
@ -73,9 +72,7 @@ void cChunkDesc::SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
void cChunkDesc::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) void cChunkDesc::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
{ {
int Index = cChunkDef::MakeIndex(a_RelX, a_RelY, a_RelZ); m_BlockArea.GetRelBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
a_BlockType = cChunkDef::GetBlock(m_BlockTypes, Index);
a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Index);
} }
@ -84,7 +81,7 @@ void cChunkDesc::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
void cChunkDesc::SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType) void cChunkDesc::SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
{ {
cChunkDef::SetBlock(m_BlockTypes, a_RelX, a_RelY, a_RelZ, a_BlockType); cChunkDef::SetBlock(m_BlockArea.GetBlockTypes(), a_RelX, a_RelY, a_RelZ, a_BlockType);
} }
@ -93,7 +90,7 @@ void cChunkDesc::SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
BLOCKTYPE cChunkDesc::GetBlockType(int a_RelX, int a_RelY, int a_RelZ) BLOCKTYPE cChunkDesc::GetBlockType(int a_RelX, int a_RelY, int a_RelZ)
{ {
return cChunkDef::GetBlock(m_BlockTypes, a_RelX, a_RelY, a_RelZ); return cChunkDef::GetBlock(m_BlockArea.GetBlockTypes(), a_RelX, a_RelY, a_RelZ);
} }
@ -102,7 +99,7 @@ BLOCKTYPE cChunkDesc::GetBlockType(int a_RelX, int a_RelY, int a_RelZ)
NIBBLETYPE cChunkDesc::GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ) NIBBLETYPE cChunkDesc::GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ)
{ {
return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ); return m_BlockArea.GetRelBlockMeta(a_RelX, a_RelY, a_RelZ);
} }
@ -111,7 +108,7 @@ NIBBLETYPE cChunkDesc::GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ)
void cChunkDesc::SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta) void cChunkDesc::SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta)
{ {
cChunkDef::SetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ, a_BlockMeta); m_BlockArea.SetRelBlockMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta);
} }
@ -242,62 +239,9 @@ bool cChunkDesc::IsUsingDefaultFinish(void) const
void cChunkDesc::WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ) void cChunkDesc::WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy)
{ {
if (!a_BlockArea.HasBlockTypes() && !a_BlockArea.HasBlockMetas()) m_BlockArea.Merge(a_BlockArea, a_RelX, a_RelY, a_RelZ, a_MergeStrategy);
{
LOGWARNING("Request was made to write a block area without BlockTypes nor BlockMetas into cChunkDesc. Ignoring.");
return;
}
int BAOffX = std::max(0, -a_RelX); // Offset in BA where to start reading
int CDOffX = std::max(0, a_RelX); // Offset in CD where to start writing
int SizeX = std::min(a_BlockArea.GetSizeX() - BAOffX, cChunkDef::Width - CDOffX); // Number of slices to write
int BAOffY = std::max(0, -a_RelY); // Offset in BA where to start reading
int CDOffY = std::max(0, a_RelY); // Offset in CD where to start writing
int SizeY = std::min(a_BlockArea.GetSizeY() - BAOffY, cChunkDef::Height - CDOffY); // Number of layers to write
int BAOffZ = std::max(0, -a_RelZ); // Offset in BA where to start reading
int CDOffZ = std::max(0, a_RelZ); // Offset in CD where to start writing
int SizeZ = std::min(a_BlockArea.GetSizeZ() - BAOffZ, cChunkDef::Width - CDOffZ); // Number of slices to write
if (a_BlockArea.HasBlockTypes())
{
for (int y = 0; y < SizeY; y++)
{
int BAY = BAOffY + y;
int CDY = CDOffY + y;
for (int z = 0; z < SizeZ; z++)
{
int BAZ = BAOffZ + z;
int CDZ = CDOffZ + z;
for (int x = 0; x < SizeX; x++)
{
int BAX = BAOffX + x;
int CDX = CDOffX + x;
cChunkDef::SetBlock(m_BlockTypes, CDX, CDY, CDZ, a_BlockArea.GetRelBlockType(BAX, BAY, BAZ));
} // for x
} // for z
} // for y
} // HasBlockTypes()
if (a_BlockArea.HasBlockMetas())
{
for (int y = 0; y < SizeY; y++)
{
int BAY = BAOffY + y;
int CDY = CDOffY + y;
for (int z = 0; z < SizeZ; z++)
{
int BAZ = BAOffZ + z;
int CDZ = CDOffZ + z;
for (int x = 0; x < SizeX; x++)
{
int BAX = BAOffX + x;
int CDX = CDOffX + x;
cChunkDef::SetNibble(m_BlockMeta, CDX, CDY, CDZ, a_BlockArea.GetRelBlockMeta(BAX, BAY, BAZ));
} // for x
} // for z
} // for y
} // HasBlockMetas()
} }
@ -437,3 +381,16 @@ HEIGHTTYPE cChunkDesc::GetMaxHeight(void) const
void cChunkDesc::CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas)
{
const NIBBLETYPE * AreaMetas = m_BlockArea.GetBlockMetas();
for (int i = 0; i < ARRAYCOUNT(a_DestMetas); i++)
{
a_DestMetas[i] = AreaMetas[2 * i] | (AreaMetas[2 * i + 1] << 4);
}
}

View File

@ -10,6 +10,7 @@
#pragma once #pragma once
#include "../ChunkDef.h" #include "../ChunkDef.h"
#include "../BlockArea.h"
@ -67,7 +68,7 @@ public:
bool IsUsingDefaultFinish(void) const; bool IsUsingDefaultFinish(void) const;
/// Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk. /// Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk.
void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ); void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy = cBlockArea::msOverwrite);
/// Reads an area from the chunk into a cBlockArea /// Reads an area from the chunk into a cBlockArea
void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ); void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ);
@ -80,24 +81,26 @@ public:
// Accessors used by cChunkGenerator::Generator descendants: // Accessors used by cChunkGenerator::Generator descendants:
inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; } inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; }
inline cChunkDef::BlockTypes & GetBlockTypes (void) { return m_BlockTypes; } inline cChunkDef::BlockTypes & GetBlockTypes (void) { return *((cChunkDef::BlockTypes *)m_BlockArea.GetBlockTypes()); }
inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return m_BlockMeta; } // CANNOT, different compression!
// inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return *((cChunkDef::BlockNibbles *)m_BlockArea.GetBlockMetas()); }
inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; } inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; }
inline cEntityList & GetEntities (void) { return m_Entities; } inline cEntityList & GetEntities (void) { return m_Entities; }
inline cBlockEntityList & GetBlockEntities(void) { return m_BlockEntities; } inline cBlockEntityList & GetBlockEntities(void) { return m_BlockEntities; }
/// Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte)
void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas);
private: private:
int m_ChunkX; int m_ChunkX;
int m_ChunkZ; int m_ChunkZ;
cChunkDef::BiomeMap m_BiomeMap; cChunkDef::BiomeMap m_BiomeMap;
cChunkDef::BlockTypes m_BlockTypes; cBlockArea m_BlockArea;
cChunkDef::BlockNibbles m_BlockMeta;
cChunkDef::HeightMap m_HeightMap; cChunkDef::HeightMap m_HeightMap;
cEntityList m_Entities; // Individual entities are NOT owned by this object! cEntityList m_Entities; // Individual entities are NOT owned by this object!
cBlockEntityList m_BlockEntities; // Individual block entities are NOT owned by this object! cBlockEntityList m_BlockEntities; // Individual block entities are NOT owned by this object!
bool m_bUseDefaultBiomes; bool m_bUseDefaultBiomes;
bool m_bUseDefaultHeight; bool m_bUseDefaultHeight;
bool m_bUseDefaultComposition; bool m_bUseDefaultComposition;

View File

@ -271,9 +271,12 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc); m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
cRoot::Get()->GetPluginManager()->CallHookChunkGenerated(m_World, a_ChunkX, a_ChunkZ, &ChunkDesc); cRoot::Get()->GetPluginManager()->CallHookChunkGenerated(m_World, a_ChunkX, a_ChunkZ, &ChunkDesc);
cChunkDef::BlockNibbles BlockMetas;
ChunkDesc.CompressBlockMetas(BlockMetas);
m_World->SetChunkData( m_World->SetChunkData(
a_ChunkX, a_ChunkY, a_ChunkZ, a_ChunkX, a_ChunkY, a_ChunkZ,
ChunkDesc.GetBlockTypes(), ChunkDesc.GetBlockMetas(), ChunkDesc.GetBlockTypes(), BlockMetas,
NULL, NULL, // We don't have lighting, chunk will be lighted when needed NULL, NULL, // We don't have lighting, chunk will be lighted when needed
&ChunkDesc.GetHeightMap(), &ChunkDesc.GetBiomeMap(), &ChunkDesc.GetHeightMap(), &ChunkDesc.GetBiomeMap(),
ChunkDesc.GetEntities(), ChunkDesc.GetBlockEntities(), ChunkDesc.GetEntities(), ChunkDesc.GetBlockEntities(),

View File

@ -20,8 +20,7 @@
void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc) void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc)
{ {
memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes())); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
for (int z = 0; z < cChunkDef::Width; z++) for (int z = 0; z < cChunkDef::Width; z++)
{ {
for (int x = 0; x < cChunkDef::Width; x++) for (int x = 0; x < cChunkDef::Width; x++)
@ -80,8 +79,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc)
E_BLOCK_BEDROCK, E_BLOCK_BEDROCK,
} ; } ;
memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes())); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
for (int z = 0; z < cChunkDef::Width; z++) for (int z = 0; z < cChunkDef::Width; z++)
{ {
@ -134,8 +132,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc)
- bedrock at the bottom - bedrock at the bottom
*/ */
memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes())); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
// The patterns to use for different situations, must be same length! // The patterns to use for different situations, must be same length!
const BLOCKTYPE PatternGround[] = {m_BlockTop, m_BlockMiddle, m_BlockMiddle, m_BlockMiddle} ; const BLOCKTYPE PatternGround[] = {m_BlockTop, m_BlockMiddle, m_BlockMiddle, m_BlockMiddle} ;
@ -191,8 +188,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc)
void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc) void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc)
{ {
memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes())); a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
int ChunkX = a_ChunkDesc.GetChunkX(); int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ(); int ChunkZ = a_ChunkDesc.GetChunkZ();

View File

@ -94,21 +94,14 @@ void cComposableGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef:
void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc)
{ {
cChunkDef::BiomeMap & BiomeMap = a_ChunkDesc.GetBiomeMap();
cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
cChunkDef::BlockNibbles & BlockMeta = a_ChunkDesc.GetBlockMetas();
cChunkDef::HeightMap & HeightMap = a_ChunkDesc.GetHeightMap();
cEntityList & Entities = a_ChunkDesc.GetEntities();
cBlockEntityList & BlockEntities = a_ChunkDesc.GetBlockEntities();
if (a_ChunkDesc.IsUsingDefaultBiomes()) if (a_ChunkDesc.IsUsingDefaultBiomes())
{ {
m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, BiomeMap); m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetBiomeMap());
} }
if (a_ChunkDesc.IsUsingDefaultHeight()) if (a_ChunkDesc.IsUsingDefaultHeight())
{ {
m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap); m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetHeightMap());
} }
if (a_ChunkDesc.IsUsingDefaultComposition()) if (a_ChunkDesc.IsUsingDefaultComposition())
@ -336,13 +329,18 @@ void cComposableGenerator::InitStructureGens(cIniFile & a_IniFile)
{ {
m_StructureGens.push_back(new cStructGenRavines(Seed, 128)); m_StructureGens.push_back(new cStructGenRavines(Seed, 128));
} }
//*
// TODO: Not implemented yet; need a name
else if (NoCaseCompare(*itr, "wormnestcaves") == 0) else if (NoCaseCompare(*itr, "wormnestcaves") == 0)
{ {
m_StructureGens.push_back(new cStructGenWormNestCaves(Seed)); m_StructureGens.push_back(new cStructGenWormNestCaves(Seed));
} }
//*/ else if (NoCaseCompare(*itr, "waterlakes") == 0)
{
m_StructureGens.push_back(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_HeightGen));
}
else if (NoCaseCompare(*itr, "lavalakes") == 0)
{
m_StructureGens.push_back(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_HeightGen));
}
else else
{ {
LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str()); LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str());

View File

@ -598,7 +598,7 @@ void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc)
case E_BLOCK_NETHERRACK: case E_BLOCK_NETHERRACK:
case E_BLOCK_STONE: case E_BLOCK_STONE:
{ {
if (TryPlaceSpring(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetBlockMetas(), x, y, z)) if (TryPlaceSpring(a_ChunkDesc, x, y, z))
{ {
// Succeeded, bail out // Succeeded, bail out
return; return;
@ -614,15 +614,11 @@ void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc)
bool cFinishGenFluidSprings::TryPlaceSpring( bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z)
cChunkDef::BlockTypes & a_BlockTypes,
cChunkDef::BlockNibbles & a_BlockMetas,
int x, int y, int z
)
{ {
// In order to place a spring, it needs exactly one of the XZ neighbors or a below neighbor to be air // In order to place a spring, it needs exactly one of the XZ neighbors or a below neighbor to be air
// Also, its neighbor on top of it must be non-air // Also, its neighbor on top of it must be non-air
if (cChunkDef::GetBlock(a_BlockTypes, x, y + 1, z) == E_BLOCK_AIR) if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR)
{ {
return false; return false;
} }
@ -641,7 +637,7 @@ bool cFinishGenFluidSprings::TryPlaceSpring(
int NumAirNeighbors = 0; int NumAirNeighbors = 0;
for (int i = 0; i < ARRAYCOUNT(Coords); i++) for (int i = 0; i < ARRAYCOUNT(Coords); i++)
{ {
switch (cChunkDef::GetBlock(a_BlockTypes, x + Coords[i].x, y + Coords[i].y, z + Coords[i].z)) switch (a_ChunkDesc.GetBlockType(x + Coords[i].x, y + Coords[i].y, z + Coords[i].z))
{ {
case E_BLOCK_AIR: case E_BLOCK_AIR:
{ {
@ -659,8 +655,7 @@ bool cFinishGenFluidSprings::TryPlaceSpring(
} }
// Has exactly one air neighbor, place a spring: // Has exactly one air neighbor, place a spring:
cChunkDef::SetBlock(a_BlockTypes, x, y, z, m_Fluid); a_ChunkDesc.SetBlockTypeMeta(x, y, z, m_Fluid, 0);
cChunkDef::SetNibble(a_BlockMetas, x, y, z, 0);
return true; return true;
} }

View File

@ -177,11 +177,7 @@ protected:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
/// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful /// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful
bool TryPlaceSpring( bool TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z);
cChunkDef::BlockTypes & a_BlockTypes,
cChunkDef::BlockNibbles & a_BlockMetas,
int x, int y, int z
);
} ; } ;

View File

@ -5,6 +5,7 @@
#include "StructGen.h" #include "StructGen.h"
#include "../BlockID.h" #include "../BlockID.h"
#include "Trees.h" #include "Trees.h"
#include "../BlockArea.h"
@ -85,18 +86,11 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
{ {
int BaseZ = ChunkZ + z - 1; int BaseZ = ChunkZ + z - 1;
cChunkDef::BlockTypes * BlT; cChunkDesc * Dest;
cChunkDef::BlockNibbles * BlM;
cChunkDef::HeightMap * Hei;
cChunkDef::BiomeMap * Bio;
if ((x != 1) || (z != 1)) if ((x != 1) || (z != 1))
{ {
BlT = &(WorkerDesc.GetBlockTypes()); Dest = &WorkerDesc;
BlM = &(WorkerDesc.GetBlockMetas());
Hei = &(WorkerDesc.GetHeightMap());
Bio = &(WorkerDesc.GetBiomeMap());
WorkerDesc.SetChunkCoords(BaseX, BaseZ); WorkerDesc.SetChunkCoords(BaseX, BaseZ);
m_BiomeGen->GenBiomes (BaseX, BaseZ, WorkerDesc.GetBiomeMap()); m_BiomeGen->GenBiomes (BaseX, BaseZ, WorkerDesc.GetBiomeMap());
@ -106,26 +100,23 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
} }
else else
{ {
BlT = &(a_ChunkDesc.GetBlockTypes()); Dest = &a_ChunkDesc;
BlM = &(a_ChunkDesc.GetBlockMetas());
Hei = &(a_ChunkDesc.GetHeightMap());
Bio = &(a_ChunkDesc.GetBiomeMap());
} }
int NumTrees = GetNumTrees(BaseX, BaseZ, *Bio); int NumTrees = GetNumTrees(BaseX, BaseZ, Dest->GetBiomeMap());
sSetBlockVector OutsideLogs, OutsideOther; sSetBlockVector OutsideLogs, OutsideOther;
for (int i = 0; i < NumTrees; i++) for (int i = 0; i < NumTrees; i++)
{ {
GenerateSingleTree(BaseX, BaseZ, i, *BlT, *BlM, *Hei, *Bio, OutsideLogs, OutsideOther); GenerateSingleTree(BaseX, BaseZ, i, *Dest, OutsideLogs, OutsideOther);
} }
sSetBlockVector IgnoredOverflow; sSetBlockVector IgnoredOverflow;
IgnoredOverflow.reserve(OutsideOther.size()); IgnoredOverflow.reserve(OutsideOther.size());
ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetBlockMetas(), OutsideOther, IgnoredOverflow); ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideOther, IgnoredOverflow);
IgnoredOverflow.clear(); IgnoredOverflow.clear();
IgnoredOverflow.reserve(OutsideLogs.size()); IgnoredOverflow.reserve(OutsideLogs.size());
ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetBlockMetas(), OutsideLogs, IgnoredOverflow); ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideLogs, IgnoredOverflow);
} // for z } // for z
} // for x } // for x
@ -136,9 +127,9 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
{ {
for (int y = cChunkDef::Height - 1; y >= 0; y--) for (int y = cChunkDef::Height - 1; y >= 0; y--)
{ {
if (cChunkDef::GetBlock(a_ChunkDesc.GetBlockTypes(), x, y, z) != E_BLOCK_AIR) if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR)
{ {
cChunkDef::SetHeight(a_ChunkDesc.GetHeightMap(), x, z, y); a_ChunkDesc.SetHeight(x, z, y);
break; break;
} }
} // for y } // for y
@ -152,10 +143,7 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenTrees::GenerateSingleTree( void cStructGenTrees::GenerateSingleTree(
int a_ChunkX, int a_ChunkZ, int a_Seq, int a_ChunkX, int a_ChunkZ, int a_Seq,
cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc & a_ChunkDesc,
cChunkDef::BlockNibbles & a_BlockMetas,
const cChunkDef::HeightMap & a_Height,
const cChunkDef::BiomeMap & a_Biomes,
sSetBlockVector & a_OutsideLogs, sSetBlockVector & a_OutsideLogs,
sSetBlockVector & a_OutsideOther sSetBlockVector & a_OutsideOther
) )
@ -163,7 +151,7 @@ void cStructGenTrees::GenerateSingleTree(
int x = (m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) / 19) % cChunkDef::Width; int x = (m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) / 19) % cChunkDef::Width;
int z = (m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) / 19) % cChunkDef::Width; int z = (m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) / 19) % cChunkDef::Width;
int Height = cChunkDef::GetHeight(a_Height, x, z); int Height = a_ChunkDesc.GetHeight(x, z);
if ((Height <= 0) || (Height > 240)) if ((Height <= 0) || (Height > 240))
{ {
@ -171,7 +159,7 @@ void cStructGenTrees::GenerateSingleTree(
} }
// Check the block underneath the tree: // Check the block underneath the tree:
BLOCKTYPE TopBlock = cChunkDef::GetBlock(a_BlockTypes, x, Height, z); BLOCKTYPE TopBlock = a_ChunkDesc.GetBlockType(x, Height, z);
if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_FARMLAND)) if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_FARMLAND))
{ {
return; return;
@ -181,7 +169,7 @@ void cStructGenTrees::GenerateSingleTree(
GetTreeImageByBiome( GetTreeImageByBiome(
a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z, a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z,
m_Noise, a_Seq, m_Noise, a_Seq,
cChunkDef::GetBiome(a_Biomes, x, z), a_ChunkDesc.GetBiome(x, z),
TreeLogs, TreeOther TreeLogs, TreeOther
); );
@ -194,7 +182,7 @@ void cStructGenTrees::GenerateSingleTree(
continue; continue;
} }
BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z); BLOCKTYPE Block = a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z);
switch (Block) switch (Block)
{ {
CASE_TREE_ALLOWED_BLOCKS: CASE_TREE_ALLOWED_BLOCKS:
@ -209,8 +197,8 @@ void cStructGenTrees::GenerateSingleTree(
} }
} }
ApplyTreeImage(a_ChunkX, a_ChunkZ, a_BlockTypes, a_BlockMetas, TreeOther, a_OutsideOther); ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeOther, a_OutsideOther);
ApplyTreeImage(a_ChunkX, a_ChunkZ, a_BlockTypes, a_BlockMetas, TreeLogs, a_OutsideLogs); ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs);
} }
@ -219,19 +207,18 @@ void cStructGenTrees::GenerateSingleTree(
void cStructGenTrees::ApplyTreeImage( void cStructGenTrees::ApplyTreeImage(
int a_ChunkX, int a_ChunkZ, int a_ChunkX, int a_ChunkZ,
cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc & a_ChunkDesc,
cChunkDef::BlockNibbles & a_BlockMetas,
const sSetBlockVector & a_Image, const sSetBlockVector & a_Image,
sSetBlockVector & a_Overflow sSetBlockVector & a_Overflow
) )
{ {
// Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks
for (sSetBlockVector::const_iterator itr = a_Image.begin(); itr != a_Image.end(); ++itr) for (sSetBlockVector::const_iterator itr = a_Image.begin(), end = a_Image.end(); itr != end; ++itr)
{ {
if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ)) if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ))
{ {
// Inside this chunk, integrate into a_BlockTypes: // Inside this chunk, integrate into a_ChunkDesc:
switch (cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z)) switch (a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z))
{ {
case E_BLOCK_LEAVES: case E_BLOCK_LEAVES:
{ {
@ -243,8 +230,7 @@ void cStructGenTrees::ApplyTreeImage(
} }
CASE_TREE_OVERWRITTEN_BLOCKS: CASE_TREE_OVERWRITTEN_BLOCKS:
{ {
cChunkDef::SetBlock (a_BlockTypes, itr->x, itr->y, itr->z, itr->BlockType); a_ChunkDesc.SetBlockTypeMeta(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
cChunkDef::SetNibble(a_BlockMetas, itr->x, itr->y, itr->z, itr->BlockMeta);
break; break;
} }
@ -271,7 +257,7 @@ int cStructGenTrees::GetNumTrees(
for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++) for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++)
{ {
int Add = 0; int Add = 0;
switch (a_Biomes[x + cChunkDef::Width * z]) switch (cChunkDef::GetBiome(a_Biomes, x, z))
{ {
case biPlains: Add = 1; break; case biPlains: Add = 1; break;
case biExtremeHills: Add = 3; break; case biExtremeHills: Add = 3; break;
@ -403,3 +389,118 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenLakes:
void cStructGenLakes::GenStructures(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
for (int z = -1; z < 2; z++) for (int x = -1; x < 2; x++)
{
cBlockArea Lake;
CreateLakeImage(ChunkX + x, ChunkZ + z, Lake);
int OfsX = Lake.GetOriginX() + x * cChunkDef::Width;
int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width;
// Merge the lake into the current data
a_ChunkDesc.WriteBlockArea(Lake, OfsX, Lake.GetOriginY(), OfsZ, cBlockArea::msLake);
} // for x, z - neighbor chunks
}
void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake)
{
a_Lake.Create(16, 8, 16);
a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy
// Find the maximum height in this chunk:
cChunkDef::HeightMap HeightMap;
m_HeiGen.GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap);
HEIGHTTYPE MaxHeight = HeightMap[0];
for (int i = 1; i < ARRAYCOUNT(HeightMap); i++)
{
if (HeightMap[i] > MaxHeight)
{
MaxHeight = HeightMap[i];
}
}
// Make a random position in the chunk by using a random 16 block XZ offset and random height up to chunk's max height
int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11;
// Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range
int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8;
Rnd >>= 12;
// Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range
int OffsetZ = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8;
Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 512, a_ChunkZ) / 13;
// Random height [0 .. MaxHeight] with preference to center heights
int HeightY = (((Rnd & 0x1ff) % (MaxHeight + 1)) + (((Rnd >> 9) & 0x1ff) % (MaxHeight + 1))) / 2;
a_Lake.SetOrigin(OffsetX, HeightY, OffsetZ);
// Hollow out a few bubbles inside the blockarea:
int NumBubbles = 4 + ((Rnd >> 18) & 0x03); // 4 .. 7 bubbles
BLOCKTYPE * BlockTypes = a_Lake.GetBlockTypes();
for (int i = 0; i < NumBubbles; i++)
{
int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, i, a_ChunkZ) / 13;
const int BubbleR = 2 + (Rnd & 0x03); // 2 .. 5
const int Range = 16 - 2 * BubbleR;
const int BubbleX = BubbleR + (Rnd % Range);
Rnd >>= 4;
const int BubbleY = 4 + (Rnd & 0x01); // 4 .. 5
Rnd >>= 1;
const int BubbleZ = BubbleR + (Rnd % Range);
Rnd >>= 4;
const int HalfR = BubbleR / 2; // 1 .. 2
const int RSquared = BubbleR * BubbleR;
for (int y = -HalfR; y <= HalfR; y++)
{
// BubbleY + y is in the [0, 7] bounds
int DistY = 4 * y * y / 3;
int IdxY = (BubbleY + y) * 16 * 16;
for (int z = -BubbleR; z <= BubbleR; z++)
{
int DistYZ = DistY + z * z;
if (DistYZ >= RSquared)
{
continue;
}
int IdxYZ = BubbleX + IdxY + (BubbleZ + z) * 16;
for (int x = -BubbleR; x <= BubbleR; x++)
{
if (x * x + DistYZ < RSquared)
{
BlockTypes[x + IdxYZ] = E_BLOCK_AIR;
}
} // for x
} // for z
} // for y
} // for i - bubbles
// Turn air in the bottom half into liquid:
for (int y = 0; y < 4; y++)
{
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
{
if (BlockTypes[x + z * 16 + y * 16 * 16] == E_BLOCK_AIR)
{
BlockTypes[x + z * 16 + y * 16 * 16] = m_Fluid;
}
} // for z, x
} // for y
// TODO: Turn sponge next to lava into stone
// a_Lake.SaveToSchematicFile(Printf("Lake_%d_%d.schematic", a_ChunkX, a_ChunkZ));
}

View File

@ -46,10 +46,7 @@ protected:
*/ */
void GenerateSingleTree( void GenerateSingleTree(
int a_ChunkX, int a_ChunkZ, int a_Seq, int a_ChunkX, int a_ChunkZ, int a_Seq,
cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc & a_ChunkDesc,
cChunkDef::BlockNibbles & a_BlockMetas,
const cChunkDef::HeightMap & a_Height,
const cChunkDef::BiomeMap & a_Biomes,
sSetBlockVector & a_OutsideLogs, sSetBlockVector & a_OutsideLogs,
sSetBlockVector & a_OutsideOther sSetBlockVector & a_OutsideOther
) ; ) ;
@ -57,8 +54,7 @@ protected:
/// Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow /// Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow
void ApplyTreeImage( void ApplyTreeImage(
int a_ChunkX, int a_ChunkZ, int a_ChunkX, int a_ChunkZ,
cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc & a_ChunkDesc,
cChunkDef::BlockNibbles & a_BlockMetas,
const sSetBlockVector & a_Image, const sSetBlockVector & a_Image,
sSetBlockVector & a_Overflow sSetBlockVector & a_Overflow
); );
@ -100,15 +96,25 @@ class cStructGenLakes :
public cStructureGen public cStructureGen
{ {
public: public:
cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid) : m_Noise(a_Seed), m_Seed(a_Seed), m_Fluid(a_Fluid) {} cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainHeightGen & a_HeiGen) :
m_Noise(a_Seed),
m_Seed(a_Seed),
m_Fluid(a_Fluid),
m_HeiGen(a_HeiGen)
{
}
protected: protected:
cNoise m_Noise; cNoise m_Noise;
int m_Seed; int m_Seed;
BLOCKTYPE m_Fluid; BLOCKTYPE m_Fluid;
cTerrainHeightGen & m_HeiGen;
// cStructureGen override: // cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override; virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
/// Creates a lake image for the specified chunk into a_Lake
void CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake);
} ; } ;