Merge pull request #2670 from cuberite/OrePockets
Added OrePockets and DirtPockets finish gens.
This commit is contained in:
commit
d6ad5245b3
@ -330,6 +330,14 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
|||||||
{
|
{
|
||||||
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDirectOverhangs(Seed)));
|
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDirectOverhangs(Seed)));
|
||||||
}
|
}
|
||||||
|
else if (NoCaseCompare(*itr, "DirtPockets") == 0)
|
||||||
|
{
|
||||||
|
auto gen = std::make_shared<cFinishGenOrePockets>(Seed + 1, cFinishGenOrePockets::DefaultNaturalPatches());
|
||||||
|
if (gen->Initialize(a_IniFile, "DirtPockets"))
|
||||||
|
{
|
||||||
|
m_FinishGens.push_back(gen);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0)
|
else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0)
|
||||||
{
|
{
|
||||||
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDistortedMembraneOverhangs(Seed)));
|
m_FinishGens.push_back(cFinishGenPtr(new cStructGenDistortedMembraneOverhangs(Seed)));
|
||||||
@ -397,52 +405,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
|||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "NaturalPatches") == 0)
|
else if (NoCaseCompare(*itr, "NaturalPatches") == 0)
|
||||||
{
|
{
|
||||||
cStructGenOreNests::OreList Ores;
|
m_FinishGens.push_back(std::make_shared<cFinishGenOreNests>(Seed + 1, cFinishGenOreNests::DefaultNaturalPatches()));
|
||||||
|
|
||||||
// Dirt vein
|
|
||||||
cStructGenOreNests::OreInfo DirtVein;
|
|
||||||
DirtVein.BlockType = E_BLOCK_DIRT;
|
|
||||||
DirtVein.MaxHeight = 127;
|
|
||||||
DirtVein.NumNests = 20;
|
|
||||||
DirtVein.NestSize = 32;
|
|
||||||
Ores.push_back(DirtVein);
|
|
||||||
|
|
||||||
// Gravel vein
|
|
||||||
cStructGenOreNests::OreInfo GravelVein;
|
|
||||||
GravelVein.BlockType = E_BLOCK_GRAVEL;
|
|
||||||
GravelVein.MaxHeight = 127;
|
|
||||||
GravelVein.NumNests = 20;
|
|
||||||
GravelVein.NestSize = 32;
|
|
||||||
Ores.push_back(GravelVein);
|
|
||||||
|
|
||||||
// Granite vein
|
|
||||||
cStructGenOreNests::OreInfo GraniteVein;
|
|
||||||
GraniteVein.BlockType = E_BLOCK_STONE;
|
|
||||||
GraniteVein.BlockMeta = 1;
|
|
||||||
GraniteVein.MaxHeight = 127;
|
|
||||||
GraniteVein.NumNests = 20;
|
|
||||||
GraniteVein.NestSize = 32;
|
|
||||||
Ores.push_back(GraniteVein);
|
|
||||||
|
|
||||||
// Diorite vein
|
|
||||||
cStructGenOreNests::OreInfo DioriteVein;
|
|
||||||
DioriteVein.BlockType = E_BLOCK_STONE;
|
|
||||||
DioriteVein.BlockMeta = 3;
|
|
||||||
DioriteVein.MaxHeight = 127;
|
|
||||||
DioriteVein.NumNests = 20;
|
|
||||||
DioriteVein.NestSize = 32;
|
|
||||||
Ores.push_back(DioriteVein);
|
|
||||||
|
|
||||||
// Andesite vein
|
|
||||||
cStructGenOreNests::OreInfo AndesiteVein;
|
|
||||||
AndesiteVein.BlockType = E_BLOCK_STONE;
|
|
||||||
AndesiteVein.BlockMeta = 5;
|
|
||||||
AndesiteVein.MaxHeight = 127;
|
|
||||||
AndesiteVein.NumNests = 20;
|
|
||||||
AndesiteVein.NestSize = 32;
|
|
||||||
Ores.push_back(AndesiteVein);
|
|
||||||
|
|
||||||
m_FinishGens.push_back(cFinishGenPtr(new cStructGenOreNests(Seed, Ores, E_BLOCK_STONE)));
|
|
||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0)
|
else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0)
|
||||||
{
|
{
|
||||||
@ -457,72 +420,19 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
|||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "NetherOreNests") == 0)
|
else if (NoCaseCompare(*itr, "NetherOreNests") == 0)
|
||||||
{
|
{
|
||||||
cStructGenOreNests::OreList Ores;
|
m_FinishGens.push_back(std::make_shared<cFinishGenOreNests>(Seed + 2, cFinishGenOreNests::DefaultNetherOres()));
|
||||||
|
|
||||||
// Quartz vein
|
|
||||||
cStructGenOreNests::OreInfo QuartzVein;
|
|
||||||
QuartzVein.BlockType = E_BLOCK_NETHER_QUARTZ_ORE;
|
|
||||||
QuartzVein.MaxHeight = 255;
|
|
||||||
QuartzVein.NumNests = 80;
|
|
||||||
QuartzVein.NestSize = 8;
|
|
||||||
Ores.push_back(QuartzVein);
|
|
||||||
|
|
||||||
m_FinishGens.push_back(cFinishGenPtr(new cStructGenOreNests(Seed, Ores, E_BLOCK_NETHERRACK)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "OreNests") == 0)
|
else if (NoCaseCompare(*itr, "OreNests") == 0)
|
||||||
{
|
{
|
||||||
cStructGenOreNests::OreList Ores;
|
m_FinishGens.push_back(std::make_shared<cFinishGenOreNests>(Seed + 3, cFinishGenOreNests::DefaultOverworldOres()));
|
||||||
|
}
|
||||||
// Coal vein
|
else if (NoCaseCompare(*itr, "OrePockets") == 0)
|
||||||
cStructGenOreNests::OreInfo CoalVein;
|
{
|
||||||
CoalVein.BlockType = E_BLOCK_COAL_ORE;
|
auto gen = std::make_shared<cFinishGenOrePockets>(Seed + 2, cFinishGenOrePockets::DefaultOverworldOres());
|
||||||
CoalVein.MaxHeight = 127;
|
if (gen->Initialize(a_IniFile, "OrePockets"))
|
||||||
CoalVein.NumNests = 50;
|
{
|
||||||
CoalVein.NestSize = 10;
|
m_FinishGens.push_back(gen);
|
||||||
Ores.push_back(CoalVein);
|
}
|
||||||
|
|
||||||
// Iron vein
|
|
||||||
cStructGenOreNests::OreInfo IronVein;
|
|
||||||
IronVein.BlockType = E_BLOCK_IRON_ORE;
|
|
||||||
IronVein.MaxHeight = 64;
|
|
||||||
IronVein.NumNests = 14;
|
|
||||||
IronVein.NestSize = 6;
|
|
||||||
Ores.push_back(IronVein);
|
|
||||||
|
|
||||||
// Gold vein
|
|
||||||
cStructGenOreNests::OreInfo GoldVein;
|
|
||||||
GoldVein.BlockType = E_BLOCK_GOLD_ORE;
|
|
||||||
GoldVein.MaxHeight = 32;
|
|
||||||
GoldVein.NumNests = 2;
|
|
||||||
GoldVein.NestSize = 6;
|
|
||||||
Ores.push_back(GoldVein);
|
|
||||||
|
|
||||||
// Redstone vein
|
|
||||||
cStructGenOreNests::OreInfo RedstoneVein;
|
|
||||||
RedstoneVein.BlockType = E_BLOCK_REDSTONE_ORE;
|
|
||||||
RedstoneVein.MaxHeight = 16;
|
|
||||||
RedstoneVein.NumNests = 4;
|
|
||||||
RedstoneVein.NestSize = 6;
|
|
||||||
Ores.push_back(RedstoneVein);
|
|
||||||
|
|
||||||
// Lapis vein
|
|
||||||
cStructGenOreNests::OreInfo LapisVein;
|
|
||||||
LapisVein.BlockType = E_BLOCK_LAPIS_ORE;
|
|
||||||
LapisVein.MaxHeight = 30;
|
|
||||||
LapisVein.NumNests = 2;
|
|
||||||
LapisVein.NestSize = 5;
|
|
||||||
Ores.push_back(LapisVein);
|
|
||||||
|
|
||||||
// Diamond vein
|
|
||||||
cStructGenOreNests::OreInfo DiamondVein;
|
|
||||||
DiamondVein.BlockType = E_BLOCK_DIAMOND_ORE;
|
|
||||||
DiamondVein.MaxHeight = 15;
|
|
||||||
DiamondVein.NumNests = 1;
|
|
||||||
DiamondVein.NestSize = 4;
|
|
||||||
Ores.push_back(DiamondVein);
|
|
||||||
|
|
||||||
m_FinishGens.push_back(cFinishGenPtr(new cStructGenOreNests(Seed, Ores, E_BLOCK_STONE)));
|
|
||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "POCPieces") == 0)
|
else if (NoCaseCompare(*itr, "POCPieces") == 0)
|
||||||
{
|
{
|
||||||
|
@ -1395,3 +1395,456 @@ eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cFinishGenOres:
|
||||||
|
|
||||||
|
void cFinishGenOres::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||||
|
{
|
||||||
|
int seq = 1;
|
||||||
|
|
||||||
|
// Generate the ores from the ore list.
|
||||||
|
for (const auto & ore: m_OreInfos)
|
||||||
|
{
|
||||||
|
GenerateOre(
|
||||||
|
a_ChunkDesc,
|
||||||
|
ore.m_BlockType, ore.m_BlockMeta,
|
||||||
|
ore.m_MaxHeight, ore.m_NumNests, ore.m_NestSize,
|
||||||
|
seq
|
||||||
|
);
|
||||||
|
seq++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const cFinishGenOres::OreInfos & cFinishGenOres::DefaultOverworldOres(void)
|
||||||
|
{
|
||||||
|
static OreInfos res
|
||||||
|
{
|
||||||
|
// OreType, OreMeta, MaxHeight, NumNests, NestSize
|
||||||
|
{E_BLOCK_COAL_ORE, 0, 127, 20, 16},
|
||||||
|
{E_BLOCK_IRON_ORE, 0, 64, 20, 8},
|
||||||
|
{E_BLOCK_GOLD_ORE, 0, 32, 2, 8},
|
||||||
|
{E_BLOCK_REDSTONE_ORE, 0, 16, 8, 7},
|
||||||
|
{E_BLOCK_DIAMOND_ORE, 0, 15, 1, 7},
|
||||||
|
{E_BLOCK_LAPIS_ORE, 0, 30, 1, 6},
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNetherOres(void)
|
||||||
|
{
|
||||||
|
static OreInfos res
|
||||||
|
{
|
||||||
|
// OreType, OreMeta, MaxHeight, NumNests, NestSize
|
||||||
|
{E_BLOCK_NETHER_QUARTZ_ORE, 0, 127, 20, 8},
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNaturalPatches(void)
|
||||||
|
{
|
||||||
|
static OreInfos res
|
||||||
|
{
|
||||||
|
// OreType, OreMeta, MaxHeight, NumNests, NestSize
|
||||||
|
{E_BLOCK_DIRT, 0, 127, 20, 32},
|
||||||
|
{E_BLOCK_GRAVEL, 0, 127, 10, 32},
|
||||||
|
{E_BLOCK_STONE, E_META_STONE_GRANITE, 127, 20, 32},
|
||||||
|
{E_BLOCK_STONE, E_META_STONE_DIORITE, 127, 20, 32},
|
||||||
|
{E_BLOCK_STONE, E_META_STONE_ANDESITE, 127, 20, 32},
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cFinishGenOres::OreInfos cFinishGenOres::OreInfosFromString(const AString & a_OreInfosString)
|
||||||
|
{
|
||||||
|
// The string is expected to be formatted as "<OreInfo1> | <OreInfo2> | <OreInfo3> | ..."
|
||||||
|
// Each OreInfo is expected to be formatted as "<OreType> : <OreMeta> : <MaxHeight> : <NumNests> : <NestSize>"
|
||||||
|
|
||||||
|
OreInfos res;
|
||||||
|
auto ores = StringSplitAndTrim(a_OreInfosString, "|");
|
||||||
|
for (const auto & ore: ores)
|
||||||
|
{
|
||||||
|
auto parts = StringSplitAndTrim(ore, ":");
|
||||||
|
if (parts.size() != 5)
|
||||||
|
{
|
||||||
|
LOGWARNING("Cannot parse ore information from string, not enough OreInfo members (exp 5, got %d). Offending item: \"%s\".",
|
||||||
|
static_cast<unsigned>(parts.size()), ore.c_str()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto oreType = BlockStringToType(parts[0]);
|
||||||
|
if (oreType < 0)
|
||||||
|
{
|
||||||
|
LOGWARNING("Cannot parse ore information from string, invalid OreType: \"%s\".", parts[0].c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NIBBLETYPE oreMeta;
|
||||||
|
int maxHeight, numNests, nestSize;
|
||||||
|
if (
|
||||||
|
!StringToInteger(parts[1], oreMeta) ||
|
||||||
|
!StringToInteger(parts[2], maxHeight) ||
|
||||||
|
!StringToInteger(parts[3], numNests) ||
|
||||||
|
!StringToInteger(parts[4], nestSize)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LOGWARNING("Cannot parse ore information from string, invalid number in OreInfo \"%s\".", ore.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res.emplace_back(oreType, oreMeta, maxHeight, numNests, nestSize);
|
||||||
|
} // for i - split[]
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cFinishGenOres::OreInfosToString(const cFinishGenOres::OreInfos & a_OreInfos)
|
||||||
|
{
|
||||||
|
AString res;
|
||||||
|
for (const auto & ore: a_OreInfos)
|
||||||
|
{
|
||||||
|
if (!res.empty())
|
||||||
|
{
|
||||||
|
res.append(" | ");
|
||||||
|
}
|
||||||
|
AppendPrintf(res, "%s:%d:%d:%d:%d",
|
||||||
|
ItemTypeToString(ore.m_BlockType).c_str(), ore.m_BlockMeta,
|
||||||
|
ore.m_MaxHeight, ore.m_NumNests, ore.m_NestSize
|
||||||
|
);
|
||||||
|
} // for ore - a_OreInfos[]
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFinishGenOres::SetSeed(int a_Seed)
|
||||||
|
{
|
||||||
|
m_Noise.SetSeed(a_Seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cFinishGenOreNests:
|
||||||
|
|
||||||
|
void cFinishGenOreNests::GenerateOre(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// This function generates several "nests" of ore, each nest consisting of number of ore blocks relatively adjacent to each other.
|
||||||
|
// It does so by making a random XYZ walk and adding ore along the way in cuboids of different (random) sizes
|
||||||
|
// Only "terraformable" blocks get replaced with ore, all other blocks stay (so the nest can actually be smaller than specified).
|
||||||
|
|
||||||
|
auto chunkX = a_ChunkDesc.GetChunkX();
|
||||||
|
auto chunkZ = a_ChunkDesc.GetChunkZ();
|
||||||
|
auto & blockTypes = a_ChunkDesc.GetBlockTypes();
|
||||||
|
auto & blockMetas = a_ChunkDesc.GetBlockMetasUncompressed();
|
||||||
|
for (int i = 0; i < a_NumNests; i++)
|
||||||
|
{
|
||||||
|
int nestRnd = m_Noise.IntNoise3DInt(chunkX + i, a_Seq, chunkZ + 64 * i) / 8;
|
||||||
|
int BaseX = nestRnd % cChunkDef::Width;
|
||||||
|
nestRnd /= cChunkDef::Width;
|
||||||
|
int BaseZ = nestRnd % cChunkDef::Width;
|
||||||
|
nestRnd /= cChunkDef::Width;
|
||||||
|
int BaseY = nestRnd % a_MaxHeight;
|
||||||
|
nestRnd /= a_MaxHeight;
|
||||||
|
int NestSize = a_NestSize + (nestRnd % (a_NestSize / 4)); // The actual nest size may be up to 1 / 4 larger
|
||||||
|
int Num = 0;
|
||||||
|
while (Num < NestSize)
|
||||||
|
{
|
||||||
|
// Put a cuboid around [BaseX, BaseY, BaseZ]
|
||||||
|
int rnd = m_Noise.IntNoise3DInt(chunkX + 64 * i, 2 * a_Seq + Num, chunkZ + 32 * i) / 8;
|
||||||
|
int xsize = rnd % 2;
|
||||||
|
int ysize = (rnd / 4) % 2;
|
||||||
|
int zsize = (rnd / 16) % 2;
|
||||||
|
rnd >>= 8;
|
||||||
|
for (int x = xsize; x >= 0; --x)
|
||||||
|
{
|
||||||
|
int BlockX = BaseX + x;
|
||||||
|
if (cChunkDef::IsValidWidth(BlockX))
|
||||||
|
{
|
||||||
|
Num++; // So that the cycle finishes even if the base coords wander away from the chunk
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int y = ysize; y >= 0; --y)
|
||||||
|
{
|
||||||
|
int BlockY = BaseY + y;
|
||||||
|
if (!cChunkDef::IsValidHeight(BlockY))
|
||||||
|
{
|
||||||
|
Num++; // So that the cycle finishes even if the base coords wander away from the chunk
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int z = zsize; z >= 0; --z)
|
||||||
|
{
|
||||||
|
int BlockZ = BaseZ + z;
|
||||||
|
if (cChunkDef::IsValidWidth(BlockZ))
|
||||||
|
{
|
||||||
|
Num++; // So that the cycle finishes even if the base coords wander away from the chunk
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Index = cChunkDef::MakeIndexNoCheck(BlockX, BlockY, BlockZ);
|
||||||
|
auto blockType = blockTypes[Index];
|
||||||
|
if ((blockType == E_BLOCK_STONE) || (blockType == E_BLOCK_NETHERRACK))
|
||||||
|
{
|
||||||
|
blockTypes[Index] = a_OreType;
|
||||||
|
blockMetas[Index] = a_OreMeta;
|
||||||
|
}
|
||||||
|
Num++;
|
||||||
|
} // for z
|
||||||
|
} // for y
|
||||||
|
} // for x
|
||||||
|
|
||||||
|
// Move the base to a neighbor voxel
|
||||||
|
switch (rnd % 4)
|
||||||
|
{
|
||||||
|
case 0: BaseX--; break;
|
||||||
|
case 1: BaseX++; break;
|
||||||
|
}
|
||||||
|
switch ((rnd >> 3) % 4)
|
||||||
|
{
|
||||||
|
case 0: BaseY--; break;
|
||||||
|
case 1: BaseY++; break;
|
||||||
|
}
|
||||||
|
switch ((rnd >> 6) % 4)
|
||||||
|
{
|
||||||
|
case 0: BaseZ--; break;
|
||||||
|
case 1: BaseZ++; break;
|
||||||
|
}
|
||||||
|
} // while (Num < NumBlocks)
|
||||||
|
} // for i - NumNests
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cFinishGenOrePockets:
|
||||||
|
|
||||||
|
bool cFinishGenOrePockets::Initialize(cIniFile & a_IniFile, const AString & a_GenName)
|
||||||
|
{
|
||||||
|
// Read the OreInfos configuration:
|
||||||
|
auto valueName = a_GenName + "_blocks";
|
||||||
|
auto pocketCfg = a_IniFile.GetValue("Generator", valueName, "");
|
||||||
|
if (pocketCfg.empty())
|
||||||
|
{
|
||||||
|
// There's no config currently stored in the INI file. Store the defaults as the config:
|
||||||
|
a_IniFile.SetValue("Generator", valueName, OreInfosToString(m_OreInfos));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_OreInfos = OreInfosFromString(pocketCfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the optional seed configuration (but do not store the default):
|
||||||
|
valueName = a_GenName + "_seed";
|
||||||
|
SetSeed(a_IniFile.GetValueI("Generator", valueName, m_Noise.GetSeed()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFinishGenOrePockets::GenerateOre(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// This function generates several "pockets" of the specified ore
|
||||||
|
// Each chunk can contain only pockets that are generated for that chunk, or for its XM / ZM neighbors.
|
||||||
|
|
||||||
|
// Generate for the 3 neighbors in the XP / ZP direction as well, so that pockets crossing the boundaries are accounted for as well:
|
||||||
|
int chunkZ = a_ChunkDesc.GetChunkZ();
|
||||||
|
int chunkX = a_ChunkDesc.GetChunkX();
|
||||||
|
imprintChunkOrePockets(chunkX - 1, chunkZ - 1, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq);
|
||||||
|
imprintChunkOrePockets(chunkX - 1, chunkZ, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq);
|
||||||
|
imprintChunkOrePockets(chunkX, chunkZ - 1, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq);
|
||||||
|
imprintChunkOrePockets(chunkX, chunkZ, a_ChunkDesc, a_OreType, a_OreMeta, a_MaxHeight, a_NumNests, a_NestSize, a_Seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFinishGenOrePockets::imprintChunkOrePockets(
|
||||||
|
int a_ChunkX, int a_ChunkZ,
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Pick a starting coord for each nest:
|
||||||
|
int baseBlockX = a_ChunkX * cChunkDef::Width;
|
||||||
|
int baseBlockZ = a_ChunkZ * cChunkDef::Width;
|
||||||
|
for (int i = 0; i < a_NumNests; i++)
|
||||||
|
{
|
||||||
|
int nestRnd = m_Noise.IntNoise3DInt(a_ChunkX + i, a_Seq, a_ChunkZ + 64 * i) / 7;
|
||||||
|
int baseX = (nestRnd % cChunkDef::Width) + baseBlockX;
|
||||||
|
nestRnd /= cChunkDef::Width;
|
||||||
|
int baseZ = (nestRnd % cChunkDef::Width) + baseBlockZ;
|
||||||
|
nestRnd /= cChunkDef::Width;
|
||||||
|
int baseY = nestRnd % a_MaxHeight;
|
||||||
|
nestRnd /= a_MaxHeight;
|
||||||
|
imprintPocket(
|
||||||
|
a_ChunkDesc,
|
||||||
|
baseX, baseY, baseZ,
|
||||||
|
a_NestSize, i + 200 * a_Seq,
|
||||||
|
a_OreType, a_OreMeta
|
||||||
|
);
|
||||||
|
} // for i - NumNests
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFinishGenOrePockets::imprintPocket(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
int a_MinPocketX, int a_PocketY, int a_MinPocketZ,
|
||||||
|
int a_NestSize, int a_Seq,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// A line segment in a random direction is chosen. Then, several spheres are formed along this line segment,
|
||||||
|
// with their diameters diminishing towards the line ends (one half of a sinusoid)
|
||||||
|
|
||||||
|
double x1 = static_cast<double>(a_MinPocketX) + 0.5;
|
||||||
|
double y1 = static_cast<double>(a_PocketY) + 0.5;
|
||||||
|
double z1 = static_cast<double>(a_MinPocketZ) + 0.5;
|
||||||
|
int rnd = m_Noise.IntNoise2DInt(a_MinPocketX + 7 * a_Seq, a_MinPocketZ + a_PocketY * 11) / 7;
|
||||||
|
double angle = static_cast<double>(rnd % 256) / (256.0 * M_PI / 2.0); // range [0 .. pi / 2]
|
||||||
|
rnd /= 256;
|
||||||
|
double length = static_cast<double>(a_NestSize) / 4.0;
|
||||||
|
double x2 = x1 + sin(angle) * length; // Always larger than x1
|
||||||
|
double z2 = z1 + cos(angle) * length; // Always larger than z1
|
||||||
|
double y2 = y1 + static_cast<double>((rnd % 3) - 1); // Up to 1 block away from y1
|
||||||
|
|
||||||
|
// Iterate over the line segment in a total of a_NestSize steps:
|
||||||
|
double stepX = (x2 - x1) / static_cast<double>(a_NestSize);
|
||||||
|
double stepY = (y2 - y1) / static_cast<double>(a_NestSize);
|
||||||
|
double stepZ = (z2 - z1) / static_cast<double>(a_NestSize);
|
||||||
|
double stepR = M_PI / static_cast<double>(a_NestSize);
|
||||||
|
double size = static_cast<double>(a_NestSize) / 16.0;
|
||||||
|
for (int i = 0; i < a_NestSize; ++i)
|
||||||
|
{
|
||||||
|
double iDbl = static_cast<double>(i);
|
||||||
|
double sphereX = x1 + stepX * iDbl;
|
||||||
|
double sphereY = y1 + stepY * iDbl;
|
||||||
|
double sphereZ = z1 + stepZ * iDbl;
|
||||||
|
double radius = (sin(stepR * iDbl) + 1.0) * size + 1.0;
|
||||||
|
imprintSphere(a_ChunkDesc, sphereX, sphereY, sphereZ, radius, a_OreType, a_OreMeta);
|
||||||
|
} // for i
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFinishGenOrePockets::imprintSphere(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
double a_SphereX, double a_SphereY, double a_SphereZ, double a_Radius,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Get the sphere's bounding box, unioned with the chunk's bounding box (possibly empty):
|
||||||
|
int baseX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||||
|
int baseZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||||
|
int minX = std::max(FloorC(a_SphereX - a_Radius), baseX);
|
||||||
|
int minY = std::max(FloorC(a_SphereY - a_Radius), 0);
|
||||||
|
int minZ = std::max(FloorC(a_SphereZ - a_Radius), baseZ);
|
||||||
|
int maxX = std::min(CeilC(a_SphereX + a_Radius), baseX + cChunkDef::Width - 1);
|
||||||
|
int maxY = std::min(CeilC(a_SphereY + a_Radius), cChunkDef::Height - 1);
|
||||||
|
int maxZ = std::min(CeilC(a_SphereZ + a_Radius), baseZ + cChunkDef::Width - 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// DEBUG:
|
||||||
|
int blockX = FloorC(a_SphereX);
|
||||||
|
int blockY = FloorC(a_SphereY);
|
||||||
|
int blockZ = FloorC(a_SphereZ);
|
||||||
|
if (
|
||||||
|
(blockX >= baseX) && (blockX < baseX + cChunkDef::Width) &&
|
||||||
|
(blockY >= 0) && (blockY < cChunkDef::Height) &&
|
||||||
|
(blockZ >= baseZ) && (blockZ < baseZ + cChunkDef::Width)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// LOGD("Imprinting a sphere center at {%d, %d, %d}", blockX, blockY, blockZ);
|
||||||
|
a_ChunkDesc.SetBlockTypeMeta(blockX - baseX, blockY, blockZ - baseZ, a_OreType, a_OreMeta);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
//*/
|
||||||
|
|
||||||
|
// Imprint the parts of the sphere intersecting the chunk:
|
||||||
|
double radiusSq = a_Radius * a_Radius / 4.0;
|
||||||
|
for (int y = minY; y <= maxY; y++)
|
||||||
|
{
|
||||||
|
double relY = static_cast<double>(y) + 0.5 - a_SphereY;
|
||||||
|
double relYSq = relY * relY;
|
||||||
|
if (relYSq > radiusSq)
|
||||||
|
{
|
||||||
|
// outside the sphere, bail out
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int z = minZ; z <= maxZ; z++)
|
||||||
|
{
|
||||||
|
double relZ = static_cast<double>(z) + 0.5 - a_SphereZ;
|
||||||
|
double relZSq = relZ * relZ;
|
||||||
|
if (relZSq + relYSq > radiusSq)
|
||||||
|
{
|
||||||
|
// outside the sphere, bail out
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int x = minX; x <= maxX; x++)
|
||||||
|
{
|
||||||
|
double relX = static_cast<double>(x) + 0.5 - a_SphereX;
|
||||||
|
double relXSq = relX * relX;
|
||||||
|
if (relZSq + relYSq + relXSq > radiusSq)
|
||||||
|
{
|
||||||
|
// outside the sphere, bail out
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int bX = x - baseX;
|
||||||
|
int bZ = z - baseZ;
|
||||||
|
auto blockType = a_ChunkDesc.GetBlockType(bX, y, bZ);
|
||||||
|
if ((blockType == E_BLOCK_STONE) || (blockType == E_BLOCK_NETHERRACK))
|
||||||
|
{
|
||||||
|
a_ChunkDesc.SetBlockTypeMeta(bX, y, bZ, a_OreType, a_OreMeta);
|
||||||
|
}
|
||||||
|
} // for x
|
||||||
|
} // for z
|
||||||
|
} // for y
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -398,3 +398,179 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Base class for generators that have an ore list attached to them.
|
||||||
|
Provides the storage and parsing for the ore list, as well as the generic plumbing for generating individual ores.
|
||||||
|
Descendants should override GenerateOre() to provide the specific ore generation technique.
|
||||||
|
Note that this class uses the "Nest" terminology for individual packs of ore, it doesn't imply any shape or algorithm. */
|
||||||
|
class cFinishGenOres:
|
||||||
|
public cFinishGen
|
||||||
|
{
|
||||||
|
typedef cFinishGen Super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct OreInfo
|
||||||
|
{
|
||||||
|
BLOCKTYPE m_BlockType; // The type of the nest.
|
||||||
|
NIBBLETYPE m_BlockMeta; // The block meta
|
||||||
|
int m_MaxHeight; // The highest possible a nest can occur
|
||||||
|
int m_NumNests; // How many nests per chunk
|
||||||
|
int m_NestSize; // The amount of blocks a nest can have.
|
||||||
|
|
||||||
|
OreInfo() :
|
||||||
|
m_BlockType(0),
|
||||||
|
m_BlockMeta(0),
|
||||||
|
m_MaxHeight(0),
|
||||||
|
m_NumNests(0),
|
||||||
|
m_NestSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
OreInfo(BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta, int a_MaxHeight, int a_NumNests, int a_NestSize) :
|
||||||
|
m_BlockType(a_OreType),
|
||||||
|
m_BlockMeta(a_OreMeta),
|
||||||
|
m_MaxHeight(a_MaxHeight),
|
||||||
|
m_NumNests(a_NumNests),
|
||||||
|
m_NestSize(a_NestSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<OreInfo> OreInfos;
|
||||||
|
|
||||||
|
cFinishGenOres(int a_Seed, const OreInfos & a_OreInfos):
|
||||||
|
m_Noise(a_Seed),
|
||||||
|
m_OreInfos(a_OreInfos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// cFinishGen overrides:
|
||||||
|
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||||
|
|
||||||
|
/** Returns a vector of OreInfo structures describing the default Overworld ores, usable in the constructor. */
|
||||||
|
static const OreInfos & DefaultOverworldOres(void);
|
||||||
|
|
||||||
|
/** Returns a vector of OreInfo structures describing the default Nether ores, usable in the constructor. */
|
||||||
|
static const OreInfos & DefaultNetherOres(void);
|
||||||
|
|
||||||
|
/** Returns a vector of OreInfo structures describing the default Overworld non-ore pockets (dirt, diorite etc), usable in the constructor. */
|
||||||
|
static const OreInfos & DefaultNaturalPatches(void);
|
||||||
|
|
||||||
|
/** Parses the parameter string into OreInfos array.
|
||||||
|
See OreInfosToString() for the complementary function.
|
||||||
|
Used for loading configuration from INI files. */
|
||||||
|
static OreInfos OreInfosFromString(const AString & a_OreInfosString);
|
||||||
|
|
||||||
|
/** Returns a string that represents the OreInfos given as the parameter.
|
||||||
|
See OreInfosFromString() for the complementary function.
|
||||||
|
Used for storing defaults in the INI file. */
|
||||||
|
static AString OreInfosToString(const OreInfos & a_OreInfos);
|
||||||
|
|
||||||
|
/** (Re-)sets the seed used by the internal generating mechanisms. */
|
||||||
|
void SetSeed(int a_Seed);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** The noise used for generating. */
|
||||||
|
cNoise m_Noise;
|
||||||
|
|
||||||
|
/** All the ores enabled in this generator. */
|
||||||
|
OreInfos m_OreInfos;
|
||||||
|
|
||||||
|
|
||||||
|
/** Generates a single ore in the specified chunk image.
|
||||||
|
a_Seq is the sequencing number (used as a complement to seed to make each ore in the same chunk have different nests) */
|
||||||
|
virtual void GenerateOre(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
// TODO: Helper function to parse a config string into m_OreInfos
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cFinishGenOreNests :
|
||||||
|
public cFinishGenOres
|
||||||
|
{
|
||||||
|
typedef cFinishGenOres Super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cFinishGenOreNests(int a_Seed, const OreInfos & a_OreInfos):
|
||||||
|
Super(a_Seed, a_OreInfos)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// cFinishGenOreClumps overrides:
|
||||||
|
virtual void GenerateOre(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
) override;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cFinishGenOrePockets:
|
||||||
|
public cFinishGenOres
|
||||||
|
{
|
||||||
|
typedef cFinishGenOres Super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cFinishGenOrePockets(int a_Seed, const OreInfos & a_OreInfos):
|
||||||
|
Super(a_Seed, a_OreInfos)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** Reads the configuration from the specified INI file.
|
||||||
|
a_GenName is the name of the generator (this class may be used for OrePockets and DirtPockets, each has a different default).
|
||||||
|
Returns true on success, false and logs errors to console on failure. */
|
||||||
|
bool Initialize(cIniFile & a_IniFile, const AString & a_GenName);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// cFinishGenOreClumps overrides:
|
||||||
|
virtual void GenerateOre(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxNestHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
) override;
|
||||||
|
|
||||||
|
/** Calculates the pockets for the specified chunk and imprints them into the specified ChunkDesc (not necessarily the same chunk).
|
||||||
|
a_Seq is the sequence number of the ore, to provide another source of randomness. */
|
||||||
|
void imprintChunkOrePockets(
|
||||||
|
int a_ChunkX, int a_ChunkZ,
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta,
|
||||||
|
int a_MaxHeight, int a_NumNests, int a_NestSize,
|
||||||
|
int a_Seq
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Imprints a single pocket of the specified ore at the specified coords into the chunk.
|
||||||
|
The pocket shape has its minimum X and Z coords specified, Y can be anywhere around the specified Y coord.
|
||||||
|
a_Seq is the sequence number of the ore, to provide another source of randomness. */
|
||||||
|
void imprintPocket(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
int a_MinPocketX, int a_PocketY, int a_MinPocketZ,
|
||||||
|
int a_NestSize, int a_Seq,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Imprints a single sphere of the specified ore at the specified coords. */
|
||||||
|
void imprintSphere(
|
||||||
|
cChunkDesc & a_ChunkDesc,
|
||||||
|
double a_SphereX, double a_SphereY, double a_SphereZ, double a_Radius,
|
||||||
|
BLOCKTYPE a_OreType, NIBBLETYPE a_OreMeta
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -272,116 +272,6 @@ int cStructGenTrees::GetNumTrees(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// cStructGenOreNests:
|
|
||||||
|
|
||||||
void cStructGenOreNests::GenFinish(cChunkDesc & a_ChunkDesc)
|
|
||||||
{
|
|
||||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
|
||||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
|
||||||
cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
|
|
||||||
cChunkDesc::BlockNibbleBytes & BlockMetas = a_ChunkDesc.GetBlockMetasUncompressed();
|
|
||||||
|
|
||||||
int seq = 1;
|
|
||||||
|
|
||||||
// Generate the ores from the ore list.
|
|
||||||
for (OreList::const_iterator itr = m_OreList.begin(); itr != m_OreList.end(); ++itr)
|
|
||||||
{
|
|
||||||
GenerateOre(ChunkX, ChunkZ, itr->BlockType, itr->BlockMeta, itr->MaxHeight, itr->NumNests, itr->NestSize, BlockTypes, BlockMetas, seq);
|
|
||||||
seq++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, NIBBLETYPE a_BlockMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc::BlockNibbleBytes & a_BlockMetas, int a_Seq)
|
|
||||||
{
|
|
||||||
// This function generates several "nests" of ore, each nest consisting of number of ore blocks relatively adjacent to each other.
|
|
||||||
// It does so by making a random XYZ walk and adding ore along the way in cuboids of different (random) sizes
|
|
||||||
// Only stone gets replaced with ore, all other blocks stay (so the nest can actually be smaller than specified).
|
|
||||||
|
|
||||||
for (int i = 0; i < a_NumNests; i++)
|
|
||||||
{
|
|
||||||
int Nestrnd = m_Noise.IntNoise3DInt(a_ChunkX + i, a_Seq, a_ChunkZ + 64 * i) / 8;
|
|
||||||
int BaseX = Nestrnd % cChunkDef::Width;
|
|
||||||
Nestrnd /= cChunkDef::Width;
|
|
||||||
int BaseZ = Nestrnd % cChunkDef::Width;
|
|
||||||
Nestrnd /= cChunkDef::Width;
|
|
||||||
int BaseY = Nestrnd % a_MaxHeight;
|
|
||||||
Nestrnd /= a_MaxHeight;
|
|
||||||
int NestSize = a_NestSize + (Nestrnd % (a_NestSize / 4)); // The actual nest size may be up to 1 / 4 larger
|
|
||||||
int Num = 0;
|
|
||||||
while (Num < NestSize)
|
|
||||||
{
|
|
||||||
// Put a cuboid around [BaseX, BaseY, BaseZ]
|
|
||||||
int rnd = m_Noise.IntNoise3DInt(a_ChunkX + 64 * i, 2 * a_Seq + Num, a_ChunkZ + 32 * i) / 8;
|
|
||||||
int xsize = rnd % 2;
|
|
||||||
int ysize = (rnd / 4) % 2;
|
|
||||||
int zsize = (rnd / 16) % 2;
|
|
||||||
rnd >>= 8;
|
|
||||||
for (int x = xsize; x >= 0; --x)
|
|
||||||
{
|
|
||||||
int BlockX = BaseX + x;
|
|
||||||
if ((BlockX < 0) || (BlockX >= cChunkDef::Width))
|
|
||||||
{
|
|
||||||
Num++; // So that the cycle finishes even if the base coords wander away from the chunk
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int y = ysize; y >= 0; --y)
|
|
||||||
{
|
|
||||||
int BlockY = BaseY + y;
|
|
||||||
if ((BlockY < 0) || (BlockY >= cChunkDef::Height))
|
|
||||||
{
|
|
||||||
Num++; // So that the cycle finishes even if the base coords wander away from the chunk
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int z = zsize; z >= 0; --z)
|
|
||||||
{
|
|
||||||
int BlockZ = BaseZ + z;
|
|
||||||
if ((BlockZ < 0) || (BlockZ >= cChunkDef::Width))
|
|
||||||
{
|
|
||||||
Num++; // So that the cycle finishes even if the base coords wander away from the chunk
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Index = cChunkDef::MakeIndexNoCheck(BlockX, BlockY, BlockZ);
|
|
||||||
if (a_BlockTypes[Index] == m_ToReplace)
|
|
||||||
{
|
|
||||||
a_BlockTypes[Index] = a_OreType;
|
|
||||||
a_BlockMetas[Index] = a_BlockMeta;
|
|
||||||
}
|
|
||||||
Num++;
|
|
||||||
} // for z
|
|
||||||
} // for y
|
|
||||||
} // for x
|
|
||||||
|
|
||||||
// Move the base to a neighbor voxel
|
|
||||||
switch (rnd % 4)
|
|
||||||
{
|
|
||||||
case 0: BaseX--; break;
|
|
||||||
case 1: BaseX++; break;
|
|
||||||
}
|
|
||||||
switch ((rnd >> 3) % 4)
|
|
||||||
{
|
|
||||||
case 0: BaseY--; break;
|
|
||||||
case 1: BaseY++; break;
|
|
||||||
}
|
|
||||||
switch ((rnd >> 6) % 4)
|
|
||||||
{
|
|
||||||
case 0: BaseZ--; break;
|
|
||||||
case 1: BaseZ++; break;
|
|
||||||
}
|
|
||||||
} // while (Num < NumBlocks)
|
|
||||||
} // for i - NumNests
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cStructGenLakes:
|
// cStructGenLakes:
|
||||||
|
|
||||||
|
@ -72,54 +72,6 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cStructGenOreNests :
|
|
||||||
public cFinishGen
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct OreInfo
|
|
||||||
{
|
|
||||||
BLOCKTYPE BlockType; // The type of the nest.
|
|
||||||
NIBBLETYPE BlockMeta; // The block meta
|
|
||||||
int MaxHeight; // The highest possible a nest can occur
|
|
||||||
int NumNests; // How many nests per chunk
|
|
||||||
int NestSize; // The amount of blocks a nest can have.
|
|
||||||
|
|
||||||
OreInfo() :
|
|
||||||
BlockType(0),
|
|
||||||
BlockMeta(0),
|
|
||||||
MaxHeight(0),
|
|
||||||
NumNests(0),
|
|
||||||
NestSize(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<OreInfo> OreList;
|
|
||||||
|
|
||||||
cStructGenOreNests(int a_Seed, OreList a_OreList, BLOCKTYPE a_ToReplace) :
|
|
||||||
m_Noise(a_Seed),
|
|
||||||
m_Seed(a_Seed),
|
|
||||||
m_OreList(a_OreList),
|
|
||||||
m_ToReplace(a_ToReplace)
|
|
||||||
{}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
cNoise m_Noise;
|
|
||||||
int m_Seed;
|
|
||||||
|
|
||||||
OreList m_OreList; // A list of possible ores.
|
|
||||||
BLOCKTYPE m_ToReplace;
|
|
||||||
|
|
||||||
// cFinishGen override:
|
|
||||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
|
||||||
|
|
||||||
void GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, NIBBLETYPE a_BlockMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc::BlockNibbleBytes & a_BlockMetas, int a_Seq);
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cStructGenLakes :
|
class cStructGenLakes :
|
||||||
public cFinishGen
|
public cFinishGen
|
||||||
{
|
{
|
||||||
|
@ -49,6 +49,7 @@ public:
|
|||||||
NOISE_DATATYPE CubicNoise3D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const;
|
NOISE_DATATYPE CubicNoise3D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const;
|
||||||
|
|
||||||
void SetSeed(int a_Seed) { m_Seed = a_Seed; }
|
void SetSeed(int a_Seed) { m_Seed = a_Seed; }
|
||||||
|
int GetSeed(void) const { return m_Seed; }
|
||||||
|
|
||||||
inline static NOISE_DATATYPE CubicInterpolate (NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct);
|
inline static NOISE_DATATYPE CubicInterpolate (NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct);
|
||||||
inline static NOISE_DATATYPE CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct);
|
inline static NOISE_DATATYPE CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct);
|
||||||
|
Loading…
Reference in New Issue
Block a user