summaryrefslogtreecommitdiffstats
path: root/src/Generating/IntGen.h
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2014-11-02 16:36:59 +0100
committerMattes D <github@xoft.cz>2014-11-02 16:36:59 +0100
commitd5b6353493868ac14b277155f398bd87f08c484c (patch)
treea7b41b3a5338582cc17c13895c8a6dff230590ce /src/Generating/IntGen.h
parentGrownProt: Added the rest of rare and M biomes. (diff)
downloadcuberite-d5b6353493868ac14b277155f398bd87f08c484c.tar
cuberite-d5b6353493868ac14b277155f398bd87f08c484c.tar.gz
cuberite-d5b6353493868ac14b277155f398bd87f08c484c.tar.bz2
cuberite-d5b6353493868ac14b277155f398bd87f08c484c.tar.lz
cuberite-d5b6353493868ac14b277155f398bd87f08c484c.tar.xz
cuberite-d5b6353493868ac14b277155f398bd87f08c484c.tar.zst
cuberite-d5b6353493868ac14b277155f398bd87f08c484c.zip
Diffstat (limited to '')
-rw-r--r--src/Generating/IntGen.h567
1 files changed, 484 insertions, 83 deletions
diff --git a/src/Generating/IntGen.h b/src/Generating/IntGen.h
index 15a5c9157..83a0e569a 100644
--- a/src/Generating/IntGen.h
+++ b/src/Generating/IntGen.h
@@ -167,7 +167,7 @@ public:
for (int x = 0; x < SizeX; x++)
{
int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7);
- a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0;
+ a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 101) % bgLandOceanMax + 1) : 0;
}
}
@@ -186,6 +186,9 @@ protected:
+/** Zooms the underlying value array to twice the size. Uses random-neighbor for the pixels in-between.
+This means that the zoome out image is randomly distorted. Applying zoom several times provides all
+the distortion that the generators need. */
template <int SizeX, int SizeZ = SizeX>
class cIntGenZoom :
public cIntGenWithNoise<SizeX, SizeZ>
@@ -212,31 +215,30 @@ public:
// Generate the underlying data with half the resolution:
int lowerMinX = a_MinX >> 1;
int lowerMinZ = a_MinZ >> 1;
- int Underlying[m_LowerSizeX * m_LowerSizeZ];
- m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, Underlying);
+ int lowerData[m_LowerSizeX * m_LowerSizeZ];
+ m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, lowerData);
const int lowStepX = (m_LowerSizeX - 1) * 2;
const int lowStepZ = (m_LowerSizeZ - 1) * 2;
- int Cache[lowStepX * lowStepZ];
+ int cache[lowStepX * lowStepZ];
// Discreet-interpolate the values into twice the size:
for (int z = 0; z < m_LowerSizeZ - 1; ++z)
{
int idx = (z * 2) * lowStepX;
- int PrevZ0 = Underlying[z * m_LowerSizeX];
- int PrevZ1 = Underlying[(z + 1) * m_LowerSizeX];
+ int PrevZ0 = lowerData[z * m_LowerSizeX];
+ int PrevZ1 = lowerData[(z + 1) * m_LowerSizeX];
for (int x = 0; x < m_LowerSizeX - 1; ++x)
{
- int ValX1Z0 = Underlying[x + 1 + z * m_LowerSizeX];
- int ValX1Z1 = Underlying[x + 1 + (z + 1) * m_LowerSizeX];
+ int ValX1Z0 = lowerData[x + 1 + z * m_LowerSizeX];
+ int ValX1Z1 = lowerData[x + 1 + (z + 1) * m_LowerSizeX];
int RndX = (x + lowerMinX) * 2;
int RndZ = (z + lowerMinZ) * 2;
- Cache[idx] = PrevZ0;
- Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1);
- idx++;
- Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0);
- Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1);
- idx++;
+ cache[idx] = PrevZ0;
+ cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ + 1, PrevZ0, PrevZ1);
+ cache[idx + 1] = super::ChooseRandomOne(RndX, RndZ - 1, PrevZ0, ValX1Z0);
+ cache[idx + 1 + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1);
+ idx += 2;
PrevZ0 = ValX1Z0;
PrevZ1 = ValX1Z1;
}
@@ -245,7 +247,7 @@ public:
// Copy from Cache into a_Values; take into account the even/odd offsets in a_Min:
for (int z = 0; z < SizeZ; ++z)
{
- memcpy(a_Values + z * SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int));
+ memcpy(a_Values + z * SizeX, cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int));
}
}
@@ -257,16 +259,18 @@ protected:
+/** Smoothes out some artifacts generated by the zooming - mostly single-pixel values.
+Compares each pixel to its neighbors and if the neighbors are equal, changes the pixel to their value. */
template <int SizeX, int SizeZ = SizeX>
class cIntGenSmooth :
public cIntGenWithNoise<SizeX, SizeZ>
{
typedef cIntGenWithNoise<SizeX, SizeZ> super;
- static const int UnderlyingSizeX = SizeX + 2;
- static const int UnderlyingSizeZ = SizeZ + 2;
+ static const int m_LowerSizeX = SizeX + 2;
+ static const int m_LowerSizeZ = SizeZ + 2;
public:
- typedef std::shared_ptr<cIntGen<UnderlyingSizeX, UnderlyingSizeZ>> Underlying;
+ typedef std::shared_ptr<cIntGen<m_LowerSizeX, m_LowerSizeZ>> Underlying;
cIntGenSmooth(int a_Seed, Underlying a_Underlying) :
@@ -279,8 +283,8 @@ public:
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
{
// Generate the underlying values:
- int Cache[UnderlyingSizeX * UnderlyingSizeZ];
- m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache);
+ int lowerData[m_LowerSizeX * m_LowerSizeZ];
+ m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerData);
// Smooth - for each square check if the surroundings are the same, if so, expand them diagonally.
// Also get rid of single-pixel irregularities (A-B-A):
@@ -289,33 +293,33 @@ public:
int NoiseZ = a_MinZ + z;
for (int x = 0; x < SizeX; x++)
{
- int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX];
- int Above = Cache[x + 1 + z * UnderlyingSizeX];
- int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX];
- int Left = Cache[x + (z + 1) * UnderlyingSizeX];
- int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX];
+ int val = lowerData[x + 1 + (z + 1) * m_LowerSizeX];
+ int above = lowerData[x + 1 + z * m_LowerSizeX];
+ int below = lowerData[x + 1 + (z + 2) * m_LowerSizeX];
+ int left = lowerData[x + (z + 1) * m_LowerSizeX];
+ int right = lowerData[x + 2 + (z + 1) * m_LowerSizeX];
- if ((Left == Right) && (Above == Below))
+ if ((left == right) && (above == below))
{
if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0)
{
- val = Left;
+ val = left;
}
else
{
- val = Above;
+ val = above;
}
}
else
{
- if (Left == Right)
+ if (left == right)
{
- val = Left;
+ val = left;
}
- if (Above == Below)
+ if (above == below)
{
- val = Above;
+ val = above;
}
}
@@ -332,7 +336,8 @@ protected:
-template<int SizeX, int SizeZ = SizeX>
+/** Converts land biomes at the edge of an ocean into the respective beach biome. */
+template <int SizeX, int SizeZ = SizeX>
class cIntGenBeaches :
public cIntGen<SizeX, SizeZ>
{
@@ -398,23 +403,24 @@ public:
};
// Generate the underlying values:
- int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ];
- m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache);
+ int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ];
+ m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues);
// Add beaches between ocean and biomes:
for (int z = 0; z < SizeZ; z++)
{
for (int x = 0; x < SizeX; x++)
{
- int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX];
- int Above = Cache[x + 1 + z * m_UnderlyingSizeX];
- int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX];
- int Left = Cache[x + (z + 1) * m_UnderlyingSizeX];
- int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX];
+ int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX];
+ int above = lowerValues[x + 1 + z * m_UnderlyingSizeX];
+ int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX];
+ int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX];
+ int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX];
if (!IsBiomeOcean(val))
{
- if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right))
+ if (IsBiomeOcean(above) || IsBiomeOcean(below) || IsBiomeOcean(left) || IsBiomeOcean(right))
{
+ // First convert the value to a regular biome (drop the M flag), then modulo by our biome count:
val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)];
}
}
@@ -431,7 +437,8 @@ protected:
-/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */
+/** Generates the underlying numbers and then randomly changes some ocean group pixels into random land
+biome group pixels, based on the predefined chance. */
template <int SizeX, int SizeZ = SizeX>
class cIntGenAddIslands :
public cIntGenWithNoise<SizeX, SizeZ>
@@ -442,9 +449,9 @@ public:
typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
- cIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) :
+ cIntGenAddIslands(int a_Seed, int a_Chance, Underlying a_Underlying) :
super(a_Seed),
- m_Threshold(a_Threshold),
+ m_Chance(a_Chance),
m_Underlying(a_Underlying)
{
}
@@ -460,17 +467,18 @@ public:
if (a_Values[x + z * SizeX] == bgOcean)
{
int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7;
- if (rnd % 100 < m_Threshold)
+ if (rnd % 1000 < m_Chance)
{
- a_Values[x + z * SizeX] = (rnd / 100) % bgLandOceanMax;
+ a_Values[x + z * SizeX] = (rnd / 1003) % bgLandOceanMax;
}
}
- }
- }
+ } // for x
+ } // for z
}
protected:
- int m_Threshold;
+ /** Chance, in permille, of an island being generated in ocean. */
+ int m_Chance;
Underlying m_Underlying;
};
@@ -502,32 +510,32 @@ public:
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values)
{
// Generate the underlying biome groups:
- int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ];
- m_Underlying->GetInts(a_MinX, a_MinZ, Cache);
+ int lowerValues[m_UnderlyingSizeX * m_UnderlyingSizeZ];
+ m_Underlying->GetInts(a_MinX, a_MinZ, lowerValues);
// Change the biomes on incompatible edges into an edge biome:
for (int z = 0; z < SizeZ; z++)
{
for (int x = 0; x < SizeX; x++)
{
- int v = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX];
- int Above = Cache[x + 1 + z * m_UnderlyingSizeX];
- int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX];
- int Left = Cache[x + (z + 1) * m_UnderlyingSizeX];
- int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX];
- switch (v)
+ int val = lowerValues[x + 1 + (z + 1) * m_UnderlyingSizeX];
+ int above = lowerValues[x + 1 + z * m_UnderlyingSizeX];
+ int below = lowerValues[x + 1 + (z + 2) * m_UnderlyingSizeX];
+ int left = lowerValues[x + (z + 1) * m_UnderlyingSizeX];
+ int right = lowerValues[x + 2 + (z + 1) * m_UnderlyingSizeX];
+ switch (val)
{
// Desert should neighbor only oceans, desert and temperates; change to temperate when another:
case bgDesert:
{
if (
- !isDesertCompatible(Above) ||
- !isDesertCompatible(Below) ||
- !isDesertCompatible(Left) ||
- !isDesertCompatible(Right)
+ !isDesertCompatible(above) ||
+ !isDesertCompatible(below) ||
+ !isDesertCompatible(left) ||
+ !isDesertCompatible(right)
)
{
- v = bgTemperate;
+ val = bgTemperate;
}
break;
} // case bgDesert
@@ -536,18 +544,18 @@ public:
case bgIce:
{
if (
- (Above == bgDesert) ||
- (Below == bgDesert) ||
- (Left == bgDesert) ||
- (Right == bgDesert)
+ (above == bgDesert) ||
+ (below == bgDesert) ||
+ (left == bgDesert) ||
+ (right == bgDesert)
)
{
- v = bgTemperate;
+ val = bgTemperate;
}
break;
} // case bgIce
}
- a_Values[x + z * SizeX] = v;
+ a_Values[x + z * SizeX] = val;
} // for x
} // for z
}
@@ -578,6 +586,9 @@ protected:
+/** Turns biome group indices into real biomes.
+For each pixel, takes its biome group and chooses a random biome from that group; replaces the value with
+that biome. */
template <int SizeX, int SizeZ = SizeX>
class cIntGenBiomes :
public cIntGenWithNoise<SizeX, SizeZ>
@@ -600,7 +611,13 @@ public:
// Define the per-biome-group biomes:
static const int oceanBiomes[] =
{
- biOcean, // biDeepOcean,
+ biOcean, // biDeepOcean,
+ };
+
+ // Same as oceanBiomes, there are no rare oceanic biomes (mushroom islands are handled separately)
+ static const int rareOceanBiomes[] =
+ {
+ biOcean,
};
static const int desertBiomes[] =
@@ -608,19 +625,29 @@ public:
biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains,
};
+ static const int rareDesertBiomes[] =
+ {
+ biMesaPlateau, biMesaPlateauF,
+ };
+
static const int temperateBiomes[] =
{
biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland,
};
+ static const int rareTemperateBiomes[] =
+ {
+ biJungle, // Jungle is not strictly temperate, but let's piggyback it here
+ };
+
static const int mountainBiomes[] =
{
biExtremeHills, biForest, biTaiga, biPlains,
};
- static const int jungleBiomes[] =
+ static const int rareMountainBiomes[] =
{
- biJungle, biJungle, biJungle, biForest,
+ biMegaTaiga,
};
static const int iceBiomes[] =
@@ -628,20 +655,28 @@ public:
biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga,
};
- static const int mesaBiomes[] =
+ // Same as iceBiomes, there's no rare ice biome
+ static const int rareIceBiomes[] =
{
- biMesa, biMesaPlateau,
+ biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga,
};
- static const cBiomesInGroups BiomesInGroups[] =
+ static const cBiomesInGroups biomesInGroups[] =
{
/* bgOcean */ { static_cast<int>(ARRAYCOUNT(oceanBiomes)), oceanBiomes},
/* bgDesert */ { static_cast<int>(ARRAYCOUNT(desertBiomes)), desertBiomes},
/* bgTemperate */ { static_cast<int>(ARRAYCOUNT(temperateBiomes)), temperateBiomes},
/* bgMountains */ { static_cast<int>(ARRAYCOUNT(mountainBiomes)), mountainBiomes},
- /* bgJungle */ { static_cast<int>(ARRAYCOUNT(jungleBiomes)), jungleBiomes},
/* bgIce */ { static_cast<int>(ARRAYCOUNT(iceBiomes)), iceBiomes},
- /* bgMesa */ { static_cast<int>(ARRAYCOUNT(mesaBiomes)), mesaBiomes},
+ };
+
+ static const cBiomesInGroups rareBiomesInGroups[] =
+ {
+ /* bgOcean */ { static_cast<int>(ARRAYCOUNT(rareOceanBiomes)), rareOceanBiomes},
+ /* bgDesert */ { static_cast<int>(ARRAYCOUNT(rareDesertBiomes)), rareDesertBiomes},
+ /* bgTemperate */ { static_cast<int>(ARRAYCOUNT(rareTemperateBiomes)), rareTemperateBiomes},
+ /* bgMountains */ { static_cast<int>(ARRAYCOUNT(rareMountainBiomes)), rareMountainBiomes},
+ /* bgIce */ { static_cast<int>(ARRAYCOUNT(rareIceBiomes)), rareIceBiomes},
};
// Generate the underlying values, representing biome groups:
@@ -654,7 +689,9 @@ public:
for (int x = 0; x < SizeX; x++)
{
int val = a_Values[x + IdxZ];
- const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)];
+ const cBiomesInGroups & Biomes = (val > bgfRare) ?
+ rareBiomesInGroups[(val & (bgfRare - 1)) % ARRAYCOUNT(rareBiomesInGroups)] :
+ biomesInGroups[val % ARRAYCOUNT(biomesInGroups)];
int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7);
a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count];
}
@@ -678,6 +715,7 @@ protected:
+/** Randomly replaces pixels of one value to another value, using the given chance. */
template <int SizeX, int SizeZ = SizeX>
class cIntGenReplaceRandomly :
public cIntGenWithNoise<SizeX, SizeZ>
@@ -713,7 +751,7 @@ public:
if (a_Values[idx] == m_From)
{
int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7;
- if (rnd % 100 < m_Chance)
+ if (rnd % 1000 < m_Chance)
{
a_Values[idx] = m_To;
}
@@ -724,9 +762,15 @@ public:
protected:
+ /** The original value to be replaced. */
int m_From;
+
+ /** The destination value to which to replace. */
int m_To;
+
+ /** Chance, in permille, of replacing the value. */
int m_Chance;
+
Underlying m_Underlying;
};
@@ -735,7 +779,9 @@ protected:
/** Mixer that joins together finalized biomes and rivers.
-It first checks for oceans; if there's no ocean, it checks for a river. */
+It first checks for oceans, if there is an ocean in the Biomes, it keeps the ocean.
+If there's no ocean, it checks Rivers for a river, if there is a river, it uses the Biomes to select either
+regular river or frozen river, based on the biome. */
template <int SizeX, int SizeZ = SizeX>
class cIntGenMixRivers:
public cIntGen<SizeX, SizeZ>
@@ -757,8 +803,8 @@ public:
{
// Generate the underlying data:
m_Biomes->GetInts(a_MinX, a_MinZ, a_Values);
- typename super::Values Rivers;
- m_Rivers->GetInts(a_MinX, a_MinZ, Rivers);
+ typename super::Values riverData;
+ m_Rivers->GetInts(a_MinX, a_MinZ, riverData);
// Mix the values:
for (int z = 0; z < SizeZ; z++)
@@ -772,7 +818,7 @@ public:
// Oceans are kept without any changes
continue;
}
- if (Rivers[idx] != biRiver)
+ if (riverData[idx] != biRiver)
{
// There's no river, keep the current value
continue;
@@ -925,7 +971,10 @@ public:
}
// If at least 3 ocean neighbors and the chance is right, change:
- if ((NumOceanNeighbors >= 3) && ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance))
+ if (
+ (NumOceanNeighbors >= 3) &&
+ ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance)
+ )
{
a_Values[x + z * SizeX] = m_ToValue;
}
@@ -1003,3 +1052,355 @@ protected:
+
+/** Adds a "rare" flag to random biome groups, based on the given chance. */
+template <int SizeX, int SizeZ = SizeX>
+class cIntGenRareBiomeGroups:
+ public cIntGenWithNoise<SizeX, SizeZ>
+{
+ typedef cIntGenWithNoise<SizeX, SizeZ> super;
+
+public:
+ typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
+
+
+ cIntGenRareBiomeGroups(int a_Seed, int a_Chance, Underlying a_Underlying):
+ super(a_Seed),
+ m_Chance(a_Chance),
+ m_Underlying(a_Underlying)
+ {
+ }
+
+
+ virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
+ {
+ // Generate the underlying data:
+ m_Underlying->GetInts(a_MinX, a_MinZ, a_Values);
+
+ // Change some of the biome groups into rare biome groups:
+ for (int z = 0; z < SizeZ; z++)
+ {
+ for (int x = 0; x < SizeX; x++)
+ {
+ int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7;
+ if (rnd % 1000 < m_Chance)
+ {
+ int idx = x + SizeX * z;
+ a_Values[idx] = a_Values[idx] | bgfRare;
+ }
+ }
+ }
+ }
+
+protected:
+ /** Chance, in permille, of changing each pixel into the rare biome group. */
+ int m_Chance;
+
+ /** The underlying generator. */
+ Underlying m_Underlying;
+};
+
+
+
+
+
+/** Changes biomes in the parent data into an alternate versions (usually "hill" variants), in such places
+that have their alterations set. */
+template <int SizeX, int SizeZ = SizeX>
+class cIntGenAlternateBiomes:
+ public cIntGenWithNoise<SizeX, SizeZ>
+{
+ typedef cIntGenWithNoise<SizeX, SizeZ> super;
+
+public:
+ typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
+
+
+ cIntGenAlternateBiomes(int a_Seed, Underlying a_Alterations, Underlying a_BaseBiomes):
+ super(a_Seed),
+ m_Alterations(a_Alterations),
+ m_BaseBiomes(a_BaseBiomes)
+ {
+ }
+
+
+ virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
+ {
+ // Generate the base biomes and the alterations:
+ m_BaseBiomes->GetInts(a_MinX, a_MinZ, a_Values);
+ super::Values alterations;
+ m_Alterations->GetInts(a_MinX, a_MinZ, alterations);
+
+ // Change the biomes into their alternate versions:
+ for (int idx = 0; idx < SizeX * SizeZ; ++idx)
+ {
+ if (alterations[idx] == 0)
+ {
+ // No change
+ continue;
+ }
+
+ // Change to alternate biomes:
+ int val = a_Values[idx];
+ switch (val)
+ {
+ case biBirchForest: val = biBirchForestHills; break;
+ case biDesert: val = biDesertHills; break;
+ case biExtremeHills: val = biExtremeHillsPlus; break;
+ case biForest: val = biForestHills; break;
+ case biIcePlains: val = biIceMountains; break;
+ case biJungle: val = biJungleHills; break;
+ case biMegaTaiga: val = biMegaTaigaHills; break;
+ case biMesaPlateau: val = biMesa; break;
+ case biMesaPlateauF: val = biMesa; break;
+ case biMesaPlateauM: val = biMesa; break;
+ case biMesaPlateauFM: val = biMesa; break;
+ case biPlains: val = biForest; break;
+ case biRoofedForest: val = biPlains; break;
+ case biSavanna: val = biSavannaPlateau; break;
+ case biTaiga: val = biTaigaHills; break;
+ }
+ a_Values[idx] = val;
+ } // for idx - a_Values[]
+ }
+
+protected:
+ Underlying m_Alterations;
+ Underlying m_BaseBiomes;
+};
+
+
+
+
+
+/** Adds an edge between two specifically incompatible biomes, such as mesa and forest. */
+template <int SizeX, int SizeZ = SizeX>
+class cIntGenBiomeEdges:
+ public cIntGenWithNoise<SizeX, SizeZ>
+{
+ typedef cIntGenWithNoise<SizeX, SizeZ> super;
+ static const int m_LowerSizeX = SizeX + 2;
+ static const int m_LowerSizeZ = SizeZ + 2;
+
+public:
+ typedef std::shared_ptr<cIntGen<m_LowerSizeX, m_LowerSizeZ>> Underlying;
+
+
+ cIntGenBiomeEdges(int a_Seed, Underlying a_Underlying):
+ super(a_Seed),
+ m_Underlying(a_Underlying)
+ {
+ }
+
+
+ virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
+ {
+ // Generate the underlying biomes:
+ Underlying::element_type::Values lowerValues;
+ m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, lowerValues);
+
+ // Convert incompatible edges into neutral biomes:
+ for (int z = 0; z < SizeZ; z++)
+ {
+ for (int x = 0; x < SizeX; x++)
+ {
+ int biome = lowerValues[x + 1 + (z + 1) * m_LowerSizeX];
+ int above = lowerValues[x + 1 + z * m_LowerSizeX];
+ int below = lowerValues[x + 1 + (z + 2) * m_LowerSizeX];
+ int left = lowerValues[x + (z + 1) * m_LowerSizeX];
+ int right = lowerValues[x + 2 + (z + 1) * m_LowerSizeX];
+
+ switch (biome)
+ {
+ case biDesert:
+ case biDesertM:
+ case biDesertHills:
+ {
+ if (
+ IsBiomeVeryCold(static_cast<EMCSBiome>(above)) ||
+ IsBiomeVeryCold(static_cast<EMCSBiome>(below)) ||
+ IsBiomeVeryCold(static_cast<EMCSBiome>(left)) ||
+ IsBiomeVeryCold(static_cast<EMCSBiome>(right))
+ )
+ {
+ biome = biPlains;
+ }
+ break;
+ } // case biDesert
+
+ case biMesaPlateau:
+ case biMesaPlateauF:
+ case biMesaPlateauFM:
+ case biMesaPlateauM:
+ {
+ if (
+ !isMesaCompatible(above) ||
+ !isMesaCompatible(below) ||
+ !isMesaCompatible(left) ||
+ !isMesaCompatible(right)
+ )
+ {
+ biome = biDesert;
+ }
+ break;
+ } // Mesa biomes
+
+ case biJungle:
+ case biJungleM:
+ {
+ if (
+ !isJungleCompatible(above) ||
+ !isJungleCompatible(below) ||
+ !isJungleCompatible(left) ||
+ !isJungleCompatible(right)
+ )
+ {
+ biome = (biome == biJungle) ? biJungleEdge : biJungleEdgeM;
+ }
+ break;
+ } // Jungle biomes
+
+ case biSwampland:
+ case biSwamplandM:
+ {
+ if (
+ IsBiomeNoDownfall(static_cast<EMCSBiome>(above)) ||
+ IsBiomeNoDownfall(static_cast<EMCSBiome>(below)) ||
+ IsBiomeNoDownfall(static_cast<EMCSBiome>(left)) ||
+ IsBiomeNoDownfall(static_cast<EMCSBiome>(right))
+ )
+ {
+ biome = biPlains;
+ }
+ break;
+ } // Swampland biomes
+ } // switch (biome)
+
+ a_Values[x + z * SizeX] = biome;
+ } // for x
+ } // for z
+ }
+
+
+protected:
+ Underlying m_Underlying;
+
+
+ bool isMesaCompatible(int a_Biome)
+ {
+ switch (a_Biome)
+ {
+ case biDesert:
+ case biMesa:
+ case biMesaBryce:
+ case biMesaPlateau:
+ case biMesaPlateauF:
+ case biMesaPlateauFM:
+ case biMesaPlateauM:
+ case biOcean:
+ case biDeepOcean:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+
+ bool isJungleCompatible(int a_Biome)
+ {
+ switch (a_Biome)
+ {
+ case biJungle:
+ case biJungleM:
+ case biJungleEdge:
+ case biJungleEdgeM:
+ case biJungleHills:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+};
+
+
+
+
+
+/** Changes biomes in the parent data into their alternate versions ("M" variants), in such places that
+have their alterations set. */
+template <int SizeX, int SizeZ = SizeX>
+class cIntGenMBiomes:
+ public cIntGenWithNoise<SizeX, SizeZ>
+{
+ typedef cIntGenWithNoise<SizeX, SizeZ> super;
+
+public:
+ typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
+
+
+ cIntGenMBiomes(int a_Seed, Underlying a_Alteration, Underlying a_Underlying):
+ super(a_Seed),
+ m_Underlying(a_Underlying),
+ m_Alteration(a_Alteration)
+ {
+ }
+
+
+ virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
+ {
+ // Generate the underlying biomes and the alterations:
+ m_Underlying->GetInts(a_MinX, a_MinZ, a_Values);
+ super::Values alterations;
+ m_Alteration->GetInts(a_MinX, a_MinZ, alterations);
+
+ // Wherever alterations are nonzero, change into alternate biome, if available:
+ for (int idx = 0; idx < SizeX * SizeZ; ++idx)
+ {
+ if (alterations[idx] == 0)
+ {
+ continue;
+ }
+
+ // Ice spikes biome was removed from here, because it was generated way too often
+ switch (a_Values[idx])
+ {
+ case biPlains: a_Values[idx] = biSunflowerPlains; break;
+ case biDesert: a_Values[idx] = biDesertM; break;
+ case biExtremeHills: a_Values[idx] = biExtremeHillsM; break;
+ case biForest: a_Values[idx] = biFlowerForest; break;
+ case biTaiga: a_Values[idx] = biTaigaM; break;
+ case biSwampland: a_Values[idx] = biSwamplandM; break;
+ case biJungle: a_Values[idx] = biJungleM; break;
+ case biJungleEdge: a_Values[idx] = biJungleEdgeM; break;
+ case biBirchForest: a_Values[idx] = biBirchForestM; break;
+ case biBirchForestHills: a_Values[idx] = biBirchForestHillsM; break;
+ case biRoofedForest: a_Values[idx] = biRoofedForestM; break;
+ case biColdTaiga: a_Values[idx] = biColdTaigaM; break;
+ case biMegaSpruceTaiga: a_Values[idx] = biMegaSpruceTaiga; break;
+ case biMegaSpruceTaigaHills: a_Values[idx] = biMegaSpruceTaigaHills; break;
+ case biExtremeHillsPlus: a_Values[idx] = biExtremeHillsPlusM; break;
+ case biSavanna: a_Values[idx] = biSavannaM; break;
+ case biSavannaPlateau: a_Values[idx] = biSavannaPlateauM; break;
+ case biMesa: a_Values[idx] = biMesaBryce; break;
+ case biMesaPlateauF: a_Values[idx] = biMesaPlateauFM; break;
+ case biMesaPlateau: a_Values[idx] = biMesaBryce; break;
+ }
+ } // for idx - a_Values[] / alterations[]
+ }
+
+protected:
+ Underlying m_Underlying;
+ Underlying m_Alteration;
+};
+
+
+
+